Analysis of golang and command source code

Keywords: Go SDK simulator Java

Some time ago, a group of friends asked a go language question in the group:

The main function of main.go calls the hello() function of demo.go. The main.go and hello.go belong to the main package. However, executing go run main.go in the directory of main.go will report that the Hello function is undefined:

The code structure is as follows:

**gopath ---- src**

          **----gohello** 

                **----hello.go** 

                    ** ----main.go**

main.go is as follows:

package main

import "fmt"

func main() {

 fmt.Println("my name is main")

 hello()
}

hello.go is as follows:

package main

import "fmt"

func hello() {
 fmt.Println("my name is hello")
}

At that time, I thought that there was a problem with his GOPATH configuration, and then I tried the same way, reported the same error and checked it on the Internet. There were two articles about this error, and also provided solutions, that is, using go run main.go hello.go, it was really OK to try.

Although it is a very simple problem, it also involves the parsing of command line parameters in the bottom layer of go language. Let's analyze the implementation of the bottom layer of the language, see what the bottom layer has done, and why is this error reported?

Analysis:

The version of Go SDK used below is 1.8.3

In this version, go supports the following 16 basic commands:

build       compile packages and dependencies
clean       remove object files
doc         show documentation for package or symbol
env         print Go environment information
bug         start a bug report
fix         run go tool fix on packages
fmt         run gofmt on package sources
generate    generate Go files by processing source
get         download and install packages and dependencies
install     compile and install packages and dependencies
list        list packages
run         compile and run Go program
test        test packages
tool        run specified go tool
version     print Go version
vet         run go tool vet on packages

In the main.go file under the src/cmd/go package of the Go SDK, the commands array of Command type supports the 16 commands:

We first know that the initialization process of go language is as follows:

Before executing the main function in main.go, initialize the import ed packages in order, and finally initialize the types and variables in main.go. When initializing to the commands array, since the definition of cmdRun is in run.go under the same package as main.go, first initialize the variables and init methods in run.go, as shown in the following code, first initialize cmdRun to Command type, and then execute in. It () function.

var cmdRun = &Command{
 UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
 Short:     "compile and run Go program",
 Long: `
Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.

By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
If the -exec flag is given, 'go run' invokes the binary using xprog:
 'xprog a.out arguments...'.
If the -exec flag is not given, GOOS or GOARCH is different from the system
default, and a program named go_$GOOS_$GOARCH_exec can be found
on the current search path, 'go run' invokes the binary using that program,
for example 'go_nacl_386_exec a.out arguments...'. This allows execution of
cross-compiled programs when a simulator or other execution method is
available.

For more about build flags, see 'go help build'.

See also: go build.
 `,
}

func init() {
 cmdRun.Run = runRun // break init loop

 addBuildFlags(cmdRun)
 cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "")
}

In init(), assign run run (in fact, the type is a method for processing the parameters after run) to cmdRu.run. addBuildFlags(cmdRun) is mainly to add command line parameters after run (for example: - x is to print all the commands used in the execution process and execute them at the same time). The other 15 commands are similar to cmdRun, each with its own run implementation.

Let's look at the main code in main.go:

for _, cmd := range commands {
   if cmd.Name() == args[0] && cmd.Runnable() {
     cmd.Flag.Usage = func() { cmd.Usage() }
     if cmd.CustomFlags {
       args = args[1:]
     } else {
       cmd.Flag.Parse(args[1:])
       args = cmd.Flag.Args()
     }
     cmd.Run(cmd, args)
     exit()
     return
   }
 }

This code traverses the commands array. When it traverses CMD run, cmd.Name() actually gets the first word run of cmdRun.UsageLine.

It will enter the if branch. Since cmd.CustomFlags is not initialized, it is false. Take the else branch and start to parse args command-line parameters. args[1:] takes all parameters after run. Then execute cmd.Run(cmd, args). For cmdRun, the first line of init() in run.go is assigned to cmdRun.run (as mentioned above, this is a function with different command implementation methods), that is, execute the runRun function in run.go. This function mainly deals with the command-line parameters as a file. If it is suffixed with_test, that is, the test file, directly reports an error. . If it is a directory, it also directly reports an error (and go run can only contain a go file with a main function). Note the line:

p := goFilesPackage(files)

In addition to verifying the file type and suffix, goFilesPackage(files) also performs stack in, load, and stack out operations. Since hello.go is not passed at startup, the system cannot find the Hello function when loading main.go, resulting in an error.

This public account provides free csdn download service and massive it learning resources. If you are ready to enter the IT pit and aspire to become an excellent program ape, these resources are suitable for you, including but not limited to java, go, python, springcloud, elk, embedded, big data, interview materials, front-end and other resources. At the same time, we have set up a technology exchange group. There are many big guys who will share technology articles from time to time. If you want to learn and improve together, you can reply [2] in the background of the public account. Free invitation plus technology exchange groups will learn from each other and share programming it related resources from time to time.

Scan the code to pay attention to the wonderful content and push it to you at the first time

Posted by gpong on Thu, 17 Oct 2019 13:59:00 -0700