一、hello world和一个示例
首先创建一个目录,并构建初始化模块
1 2 3 4 5 6 cd mkdir hello cd hellogo mod init example/hello
hello.go
代码
1 2 3 4 5 6 7 8 9 10 package mainimport "fmt" import "rsc.io/quote" func main () { fmt.Println("hello, World!" ) fmt.Println(quote.Go()) }
下载依赖模块
执行代码
二、自定义模块
新建一个greetings目录,并初始化模块
1 2 3 4 5 cd mkdir greetings cd greetingsgo mod init example.com/greetings
新建greetings.go
文件,代码如下
1 2 3 4 5 6 7 8 9 package greetingsimport "fmt" func Hello (name string ) string { message := fmt.Sprintf("Hi, %v. Welcome!" , name) return message }
三、引入自定义模块
新建一个hello模块,并初始化(同第一步)
1 2 3 4 5 cd mkdir hello cd hellogo mod init example.com/hello
编辑hello.go
代码,引入example.com/greetings
模块
1 2 3 4 5 6 7 8 9 10 11 package mainimport ( "fmt" "example.com/greetings" ) func main () { message := greetings.Hello("Zerchin" ) fmt.Println(message) }
正常example.com是一个可访问的地址,这里由于是我们自定义的模块,所以需要替换成本地路径,如下
1 go mod edit -replace example.com/greetings=../greetings
查看go.mod
文件可以看到多了一行replace xxxx
添加自定义模块
查看go.mod
文件可以看到多了一行require xxx
执行代码
输出
四、返回错误并处理
编辑greetings/greetings.go
文件,加入错误处理代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package greetingsimport ( "fmt" "errors" ) func Hello (name string ) (string , error) { if name == "" { return "" , errors.New("empty name" ) } message := fmt.Sprintf("Hi, %v. Welcome!" , name) return message, nil }
编辑hello/hello.go
文件,加入错误日志输出代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport ( "fmt" "log" "example.com/greetings" ) func main () { log.SetPrefix("greetings: " ) log.SetFlags(0 ) message, err := greetings.Hello("" ) if err != nil { log.Fatal(err) }
输出如下:
1 2 3 $ go run . greetings: empty name exit status 1
五、随机返回问候语
编辑greetings/greetings.go
文件,加入随机返回问候语的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package greetingsimport ( "fmt" "errors" "math/rand" "time" ) func Hello (name string ) (string , error) { if name == "" { return "" , errors.New("empty name" ) } message := fmt.Sprintf(randomFormat(), name) return message, nil } func init () { rand.Seed(time.Now().UnixNano()) } func randomFormat () string { formats := []string { "Hi, %v. Welcome!" , "Great to see youm %v" , "Hail, %v! Well met!" , } return formats[rand.Intn(len (formats))] }
编辑hello/hello.go
文件,调用随机问候语
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package main import ( "fmt" "log" "example.com/greetings" ) func main () { // 设置日志的属性 log.SetPrefix("greetings: " ) log.SetFlags(0) message, err := greetings.Hello("Zerchin" ) // 错误处理 if err != nil { log.Fatal(err) } fmt.Println(message) }
执行代码
1 2 3 4 5 6 $ go run . Hail, Zerchin! Well met! $ go run . Great to see youm Zerchin $ go run . Hi, Zerchin. Welcome!
六、回复多人问候 这里新增一个函数去调用原有的函数
编辑greetings/greetings.go
文件,新增一个Hellos函数,并去调用Hello函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package greetingsimport ( "fmt" "errors" "math/rand" "time" ) func Hello (name string ) (string , error) { if name == "" { return "" , errors.New("empty name" ) } message := fmt.Sprintf(randomFormat(), name) return message, nil } func Hellos (names []string ) (map [string ]string , error) { messages := make (map [string ]string ) for _,name := range names { message, err := Hello(name) if err != nil { return nil , err } messages[name] = message } return messages, nil } func init () { rand.Seed(time.Now().UnixNano()) } func randomFormat () string { formats := []string { "Hi, %v. Welcome!" , "Great to see youm %v" , "Hail, %v! Well met!" , } return formats[rand.Intn(len (formats))] }
编辑hello/hello.go
文件,传递一组names到Hellos函数上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package mainimport ( "fmt" "log" "example.com/greetings" ) func main () { log.SetPrefix("greetings: " ) log.SetFlags(0 ) names := []string {"Zerchin" , "Zing" , "xzq" } message, err := greetings.Hellos(names) if err != nil { log.Fatal(err) } fmt.Println(message) }
执行代码
1 2 $ go run . map[Zerchin:Hail, Zerchin! Well met! Zing:Hail, Zing! Well met! xzq:Hi, xzq. Welcome!]
七、代码单元测试 Go 的testing
包和go test
命令,您可以快速编写和执行测试。
以_test.go
结尾的文件名告诉go test
命令该文件包含测试函数,所以新建一个greetings_test.go
文件,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package greetingsimport ( "testing" "regexp" ) func TestHelloName (t *testing.T) { name := "Zerchin" want := regexp.MustCompile(`\b` + name + `\b` ) msg, err := Hello("Zerchin" ) if !want.MatchString(msg) || err != nil { t.Fatalf(`Hello("Zerchin") = %q, %v, want match for %#q, nil` , msg, err, want) } } func TestHelloEmpty (t *testing.T) { msg, err := Hello("" ) if msg != "" || err == nil { t.Fatalf(`Hello("") = %q, %v, want "", error` , msg, err) } }
执行go test
命令进行测试
1 2 3 4 5 6 7 8 9 10 11 $ go test PASS ok example.com/greetings 0.005s $ go test -v === RUN TestHelloName --- PASS: TestHelloName (0.00s) === RUN TestHelloEmpty --- PASS: TestHelloEmpty (0.00s) PASS ok example.com/greetings 0.007
修改greetings.go
代码,假设代码有误,如下:
1 2 3 4 5 6 7 8 9 10 11 func Hello (name string ) (string , error) { if name == "" { return "" , errors.New("empty name" ) } message := fmt.Sprintf(randomFormat()) return message, nil }
测试异常的结果
1 2 3 4 5 6 $ go test --- FAIL: TestHelloName (0.00s) greetings_test.go:14: Hello("Zerchin" ) = "Hi, %!v(MISSING). Welcome!" , <nil>, want match for `\bZerchin\b`, nil FAIL exit status 1FAIL example.com/greetings 0.005s
八、编译并安装应用程序
go build
:编辑包及其依赖项,但不安装
go install
:编辑并安装软件包
进入到hello目录,执行go build
命令将代码编译为可执行文件
验证结果
1 2 $ ./hello map[Zerchin:Hail, Zerchin! Well met! Zing:Great to see youm Zing xzq:Hi, xzq. Welcome!]
此时可执行文件在当前目录下,需要手动执行路径才能执行
所以,可以通过go install
命令将文件安装到go的PATH路径下
查看Go的安装路径
1 2 $ go list -f '{{.Target}}' /Users/zerchin/go/bin/hello
添加该路径到PATH路径下
1 export PATH=$PATH :/Users/zerchin/go/bin/
可以通过 go env -w GOBIN=/path/to/your/bin
命令设置环境变量修改安装路径
执行go install
命令对代码进行编译和安装
测试结果,可以直接执行hello命令
1 2 3 $ hello map[Zerchin:Great to see youm Zerchin Zing:Great to see youm Zing xzq:Hi, xzq. Welcome!]