title: [Learning Documents][Golang] Useful Package go-internal Extracted from Go Source Code
published: false
date: 2022-08-22 00:00:00 UTC
tags:
canonical_url: http://www.evanlin.com/til-go-use-go-internal/
---
> Released a new version of [@rogpeppe](https://twitter.com/rogpeppe?ref_src=twsrc%5Etfw)'s go-internal with some notable changes to testscript, used heavily in [@cue\_lang](https://twitter.com/cue_lang?ref_src=twsrc%5Etfw) :) A special thanks to [@bitfield](https://twitter.com/bitfield?ref_src=twsrc%5Etfw), [@tomwpayne](https://twitter.com/tomwpayne?ref_src=twsrc%5Etfw), and [@FiloSottile](https://twitter.com/FiloSottile?ref_src=twsrc%5Etfw) for their recent contributions! [#golang](https://twitter.com/hashtag/golang?src=hash&ref_src=twsrc%5Etfw)[https://t.co/hDAqsecssu](https://t.co/hDAqsecssu)
>
> — Daniel Martí (@mvdan\_) [August 23, 2022](https://twitter.com/mvdan_/status/1561967605073723392?ref_src=twsrc%5Etfw)
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
One day, this [tweet](https://twitter.com/mvdan_/status/1561967605073723392) caught my attention, and it also mentioned:
- Former Google security guru [@FiloSottile](https://twitter.com/FiloSottile)
- The author of Power of Go, [@bitfield](https://twitter.com/bitfield)
This made me seriously want to understand what [Go-Internal](https://github.com/rogpeppe/go-internal) is.
## What is Go-Internal
#### Location: [https://github.com/rogpeppe/go-internal](https://github.com/rogpeppe/go-internal)
I wonder if anyone else is like me, sometimes when looking at golang source code, you come across some tools or funcs that are quite useful. At that moment, you might copy and use them. Or extract some of the essence. But in many cases, many funcs, after being organized, can often become very convenient tools.
And [https://github.com/rogpeppe/go-internal](https://github.com/rogpeppe/go-internal) is a small package that independently extracts and reorganizes Go Internal source code for use. In fact, there are many useful small tools inside.
Here are a few small tools, let me share them:
### About the go-Internal/testscript package
**testscript**: script-based testing based on txtar files
This tool provides a test package that allows you to test cli command apps. You might not know it just by looking at it, how to use `testscript`. But the introduction from [Reddit](https://www.reddit.com/r/golang/comments/c67zv0/unit_testing_cobra/) is quite clear.
testscript was factored out of the cmd/go internals where it is used to test the go command itself in various combinations/permutations.
You can also refer to a piece of code from [flowdev](https://github.com/flowdev)/**[spaghetti-analyzer](https://github.com/flowdev/spaghetti-analyzer)** [main\_test.go](https://github.com/flowdev/spaghetti-analyzer/blob/2c8b0a97c4c1c24190ae221ff41323d5d53642b1/main_test.go)
func TestAnalyze(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata",
Cmds: map[string]func(*testscript.TestScript, bool, []string){
"analyze": func(ts *testscript.TestScript, _ bool, args []string) {
expectedReturnCode, err := strconv.Atoi(args[0])
if err != nil {
ts.Fatalf("fatal return code error (%q): %v", args[0], err)
}
args = args[1:]
actualReturnCode := analyze(args)
if actualReturnCode != expectedReturnCode {
ts.Fatalf("Expected return code %d but got: %d", expectedReturnCode, actualReturnCode)
}
},
},
TestWork: false,
})
}
This code reads the files in the `testdata` folder, and then runs the cli test cases inside to run your Cli app.
### About the go-Internal/testenv package
This package is quite interesting, it can find the current system's golang related environment parameters. For example, it can execute the `go run` environment.
package main
import (
"fmt"
"github.com/rogpeppe/go-internal/testenv"
)
func main() {
fmt.Println(testenv.HasGoRun())
}
This code can check if your docker image has a `go run` environment. You can see the detailed testenv source code [here](https://github.com/rogpeppe/go-internal/blob/master/testenv/testenv.go).
### About the go-Internal/par package
_Package par implements parallel execution helpers._ It can provide you with many _parallel_ helpers.
import (
"fmt"
"sync/atomic"
"time"
"github.com/rogpeppe/go-internal/par"
)
func main() {
var w par.Work
const N = 100
for i := 0; i < N; i++ {
w.Add(i)
}
start := time.Now()
var n int32
w.Do(N, func(x interface{}) {
time.Sleep(1 * time.Millisecond)
fmt.Println(n)
atomic.AddInt32(&n, +1)
})
if n != N {
fmt.Println("par.Work.Do did not do all the work")
}
if time.Since(start) < N/2*time.Millisecond {
fmt.Println("done!")
return
}
}
This way, you can have 1 ~ 100 different _parallel_ processes running at the same time.
## Small Conclusion:
By chance, I saw a tweet and saw such a useful small tool, and the key is that it's maintained by several大神. Those who are interested can continue to pay attention.
## Related Articles:
- [Reddit: Unit Testing Cobra](https://www.reddit.com/r/golang/comments/c67zv0/unit_testing_cobra/)
- [Tweet about go-internal 1.9 release](https://twitter.com/mvdan_/status/1561967605073723392)
Top comments (0)