gofumpt比默认的gofmt更严格
安装gofumpt到local go workspace
export GOPATH=/home/gpadmin/go
export GOBIN=$GOPATH/bin
go get mvdan.cc/gofumpt
// Go 1.17以后,推荐go install
go install mvdan.cc/gofumpt@latest
配置gofumpt
// .vimrc,配置后适用于vim-go
let g:go_fmt_command = "gofumpt"
// coc-settings.json,适用于coc.nvim
{
"go.formatTool": "gofumpt"
}
使用gofumpt
// 命令行,-w代表原地修改
gofumpt -w .
// vim-go
:GoFmt
或者修改后自动fmt
init本地project
go mod init my-local-project
get 指定版本的包
go get github.com/lib/pq@v1.2.0
代码中删除了某个依赖,并且想要从go.mod中清除它
go mod tidy
构建,基于go.mod里的模块版本
go build
go test
重新初始化模块,有时候需要用到,如go build总是不产生可执行程序。
rm go.mod go.sum
go mod init exec_example
go get
go build
国内设置golang proxy
[mxadmin@dw1-cn exec]$ go get github.com/lib/pq
go: module github.com/lib/pq: Get "https://proxy.golang.org/github.com/lib/pq/@v/list": dial tcp 142.251.43.17:443: i/o timeout
[mxadmin@dw1-cn exec]$ go env -w GOPROXY=https://goproxy.cn,direct
[mxadmin@dw1-cn exec]$ go get github.com/lib/pq
go: downloading github.com/lib/pq v1.10.9
go: added github.com/lib/pq v1.10.9
插件、驱动初始化
在Go中,引入一个包并使用下划线作为其别名意味着只初始化该包并调用其init()函数(如果存在),但不使用该包中的任何其他函数或变量。这通常用于那些作为驱动或插件提供的包,这些驱动或插件在被导入时需要进行一些初始化工作。
下面例子导入了github.com/lib/pq包,该包为Go的database/sql提供了PostgreSQL数据库驱动。导入此包的目的是注册该驱动,使其可以在database/sql中使用。实际上,github.com/lib/pq包的init()函数负责这项工作,所以您只需导入它,而不必在代码中显式引用它。
这种导入方式使您可以在程序中使用标准的database/sql接口与PostgreSQL数据库进行交互,而不必直接使用github.com/lib/pq提供的任何特定函数或类型。
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
引用
在Go中,切片(slice)、映射(map)和通道(channel)这三种类型的变量都是引用类型。这意味着当你将一个映射赋值给另一个变量时,实际上是将原映射的引用赋值给了新变量。因此,对新变量进行的任何修改也会影响到原映射,反之亦然。
下面例子,chState 和 session.ChState 都引用相同的底层映射数据结构,所以对其中一个进行的任何修改都会影响到另一个。
type Session struct {
ChState map[string] int
}
chState := session.ChState
chState[segmentID] = ChStateIdle
map的值
在 Go 中,map 中的值在访问时都会被复制。
chState 是从 session.ChState[segmentID] 获得的映射值的拷贝。因此,改变 chState 的值并不会影响 session.ChState[segmentID] 的值。
chState, exists := session.ChState[segmentID]
if exists {
chState = Idle
}
判断map中key是否存在
if value, ok := myMap[key]; ok {
// key exists in the map, and its value is stored in the variable 'value'
}
命令行参数
os.Args
package main
import (
"fmt"
"os"
)
func main() {
// Check the number of arguments
if len(os.Args) < 2 {
fmt.Println("Usage:", os.Args[0], "<param1> <param2> ...")
return
}
// Print all arguments
for i, arg := range os.Args {
fmt.Printf("Argument %d: %s\n", i, arg)
}
}
$ go run main.go arg1 arg2 arg3
Argument 0: /tmp/go-build/main
Argument 1: arg1
Argument 2: arg2
Argument 3: arg3
flag
package main
import (
"flag"
"fmt"
)
func main() {
// Define flags
name := flag.String("name", "Guest", "Your name")
age := flag.Int("age", 0, "Your age")
var country string
flag.StringVar(&country, "country", "Unknown", "Your country")
// Parse the flags
flag.Parse()
// Use the flag values
fmt.Printf("Hello, %s! You are %d years old.\n", *name, *age)
}
$ go run main.go -name=John -age=30
Hello, John! You are 30 years old.
synchronization 相关
channels 或者WaitGroup通常更简单,能应对大多数场景。sync.Mutex更复杂但应对的场景更加广泛。
var wg sync.WaitGroup
func myGoroutine() {
// Some setup or initialization code
wg.Done() // Signal that the setup is complete
// Rest of the goroutine logic
}
func main() {
wg.Add(1)
go myGoroutine()
wg.Wait() // Wait for the goroutine to signal that it's ready
// Continue with the main logic
}
var m sync.Mutex
var ready = false
var cond = sync.NewCond(&m)
func myGoroutine() {
m.Lock()
// Some setup or initialization code
ready = true
m.Unlock()
cond.Broadcast() // Signal that the setup is complete
// Rest of the goroutine logic
}
func main() {
go myGoroutine()
m.Lock()
for !ready { // Wait for the condition to be true
cond.Wait()
}
m.Unlock()
// Continue with the main logic
}
readyChan := make(chan struct{})
func myGoroutine() {
// Some setup or initialization code
close(readyChan) // Signal that the setup is complete
// Rest of the goroutine logic
}
func main() {
go myGoroutine()
<-readyChan // Wait for the goroutine to signal that it's ready
// Continue with the main logic
}
goroutine退出行为
goroutine A启动goroutine B,A退出后,B不会退出。但是main routine退出后,所有相关的goroutine都会退出。见下面链接中的例子
https://verinumbenator.medium.com/do-go-routines-end-when-the...
package main
import (
"fmt"
"time"
)
func main() {
defer println("Main Function Returned Here")
CallingFunction()
time.Sleep(5 * time.Second) //wait to see
}
func CallingFunction() {
defer println("Calling Function Returned Here")
dataCh := make(chan struct{})
// Start a goroutine that runs an infinite loop that prints a message and sleeps for 1 second in each iteration
go func(ch chan struct{}) {
for i := 0; ; i++ {
fmt.Println("goroutine running: ", i)
if i == 3 {
ch <- struct{}{}
}
time.Sleep(1 * time.Second)
}
}(dataCh)
// Wait for a value to be received on the dataCh channel
<-dataCh
return
}
output:
goroutine running: 0
goroutine running: 1
goroutine running: 2
goroutine running: 3
Calling Function Returned Here
goroutine running: 4
goroutine running: 5
goroutine running: 6
goroutine running: 7
Main Function Returned Here
Program exited.
学习资料:
电子书
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。