在golang中的每个模块可以,定义init函数,用来初始化该包内的全局变量,我们可以看看它的特点
package main
import "fmt"
func init() {
fmt.Println("init 1")
}
func init() {
fmt.Println("init 2")
}
func main() {
fmt.Println("main") // 输出 init 1, init2 main
}
Go has many features. Some are unique, some are borrowed from other programming languages:
- built-in concurrent programming support
- goroutines (green threads) and start new goroutines easily.
- channels (based on CSP model) and select mechanisms to do synchronizations
- between goroutines.
- the container types map and slice are first-class citizens.
- polymorphism through interfaces.
- value boxing and reflection through interfaces.
- pointers.
- function closures.
- methods.
- deferred function calls.
- type embedding.
- type deduction.
- memory safety.
- automatic garbage collection.
- great cross-platform compatibility.
sync.Mutex使用错误
package main
import (
"fmt"
"sync"
"time"
)
type Container struct {
sync.Mutex // <-- Added a mutex
counters map[string]int
}
func (c Container) inc(name string) {
c.Lock() // <-- Added locking of the mutex
defer c.Unlock()
c.counters[name]++
}
func main() {
c := Container{counters: map[string]int{"a": 0, "b": 0}}
doIncrement := func(name string, n int) {
for i := 0; i < n; i++ {
c.inc(name)
}
}
go doIncrement("a", 100000)
go doIncrement("a", 100000)
// Wait a bit for the goroutines to finish
time.Sleep(300 * time.Millisecond)
fmt.Println(c.counters)
}
输出:
fatal error: concurrent map writes
goroutine 5 [running]:
runtime.throw(0x4b765b, 0x15)
<...> more goroutine stacks
exit status 2
原因是什么,因为inc的receiver是值类型,而不是指针,而Mutex是值类型,所以会拷贝mutex,而map是引用类型,所以mutex保护不了map。证明:
package main
import "fmt"
type Container struct {
i int
s string
}
func (c Container) byValMethod() {
fmt.Printf("byValMethod got &c=%p, &(c.s)=%p\n", &c, &(c.s))
}
func (c *Container) byPtrMethod() {
fmt.Printf("byPtrMethod got &c=%p, &(c.s)=%p\n", c, &(c.s))
}
func main() {
var c Container
fmt.Printf("in main &c=%p, &(c.s)=%p\n", &c, &(c.s))
c.byValMethod()
c.byPtrMethod()
}
输出
in main &c=0xc00000a060, &(c.s)=0xc00000a068
byValMethod got &c=0xc00000a080, &(c.s)=0xc00000a088
byPtrMethod got &c=0xc00000a060, &(c.s)=0xc00000a068
Go 私有包的构建和使用
https://www.chenshaowen.com/blog/building-and-using-go-private-packages.html
使用私有仓库