Open gobomb opened 5 years ago
https://go101.org/article/channel-closing.html
关闭channel的方法
限制goroutine的数量
package gpool
import (
"sync"
)
type pool struct {
queue chan int
wg *sync.WaitGroup
}
func New(size int) *pool {
if size <= 0 {
size = 1
}
return &pool{
queue: make(chan int, size),
wg: &sync.WaitGroup{},
}
}
func (p *pool) Add(delta int) {
for i := 0; i < delta; i++ {
p.queue <- 1
}
for i := 0; i > delta; i-- {
<-p.queue
}
p.wg.Add(delta)
}
func (p *pool) Done() {
<-p.queue
p.wg.Done()
}
func (p *pool) Wait() {
p.wg.Wait()
}
package gpool_test
import (
"runtime"
"testing"
"time"
"gpool"
)
func Test_Example(t *testing.T) {
pool := gpool.New(100)
println(runtime.NumGoroutine())
for i := 0; i < 1000; i++ {
pool.Add(1)
go func() {
time.Sleep(time.Second)
println(runtime.NumGoroutine())
pool.Done()
}()
}
pool.Wait()
println(runtime.NumGoroutine())
}
grpcui -plaintext -bind 0.0.0.0 -proto proto/orca.proto 10.10.13.7:1400
grpc 调试工具(类似postman之于http)
go mod 系列博客阅读笔记
https://blog.golang.org/using-go-modules
Starting in Go 1.13, module mode will be the default for all development.
The indirect comment indicates a dependency is not used directly by this module, only indirectly by other module dependencies.
Each different major version (v1, v2, and so on) of a Go module uses a different module path: starting at v2, the path must end in the major version.
go build
, go test
, and other package-building commands add new dependencies to go.mod as needed.
go mod tidy
removes unused dependencies.
Note that when go mod tidy adds a requirement, it adds the latest version of the module.
The version referenced in a go.mod may be an explicit release tagged in the repository (for example, v1.5.2), or it may be a pseudo-version based on a specific commit (for example, v0.0.0-20170915032832-14c0d48ead0c). Pseudo-versions are a special type of pre-release version. Pseudo-versions are useful when a user needs to depend on a project that has not published any semantic version tags, or develop against a commit that hasn't been tagged yet, but users should not assume that pseudo-versions provide a stable or well-tested API.
Sometimes, maintaining backwards compatibility can lead to awkward APIs. That's OK. An imperfect API is better than breaking users' existing code.
If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.
Pseudo-versions never need to be typed by hand: the go command will accept the plain commit hash and translate it into a pseudo-version (or a tagged version if available) automatically.
var slis []*string = []*string{&a, &b, &c}
for _, s := range slis {
fmt.Printf("in for:\t %p \t---- %p\n", s, &s)
//time.Sleep(1 * time.Second)
go func() {
fmt.Printf("in func:\t %p \t---- %p\n", s, &s)
}()
go func(s *string) {
fmt.Printf("in func(s):\t %p \t---- %p\n", s, &s)
}(s)
}
time.Sleep(2 * time.Second)
goroutine 闭包如果不通过传参的方式使用指针,在for循环中,因为指针会被赋值,是共享的,可能会导致读到了更新过的值。通过参数传递的话,就能够保证每个 goroutine 用了不同的指针。
in for: 0xc000010250 ---- 0xc00000e030
in for: 0xc000010260 ---- 0xc00000e030
in for: 0xc000010270 ---- 0xc00000e030
in func: 0xc000010260 ---- 0xc00000e030
in func: 0xc000010270 ---- 0xc00000e030
in func(s): 0xc000010270 ---- 0xc00000e040
in func: 0xc000010270 ---- 0xc00000e030
in func(s): 0xc000010260 ---- 0xc00009e000
in func(s): 0xc000010250 ---- 0xc000100000
https://blog.chewxy.com/2018/03/18/golang-interfaces/
从使用者定义interface
https://blog.golang.org/laws-of-reflection
A variable of interface type stores a pair: the concrete value assigned to the variable, and that value's type descriptor. To be more precise, the value is the underlying concrete data item that implements the interface and the type describes the full type of that item. ... One important detail is that the pair inside an interface always has the form (value, concrete type) and cannot have the form (value, interface type). Interfaces do not hold interface values.
github.com/cweill/gotests/gotests
gotests -all -w filepath
自动生成单元测试模板
The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values.
An interface value is nil only if the V and T are both unset, (T=nil, V is not set), In particular, a nil interface will always hold a nil type. If we store a nil pointer of type int inside an interface value, the inner type will be int regardless of the value of the pointer: (T=*int, V=nil). Such an interface value will therefore be non-nil even when the pointer value V inside is nil.
interface只有type和value同时为nil,才 ==nil
for _, v := range values{}
v使用的都是同一个变量
Go has no 'reference types'
https://github.com/golang/go/commit/b34f0551387fcf043d65cd7d96a0214956578f94
s := "hi你好"
fmt.Println(len(s)) //8 = 1+1+3+3
//golang中的unicode/utf8包提供了用utf-8获取长度的方法
fmt.Println("RuneCountInString:", utf8.RuneCountInString(s)) //4
//通过rune类型处理unicode字符
fmt.Println("rune:", len([]rune(s))) //4
golang中string底层是通过byte数组实现的。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8。
On error, any Response can be ignored. A non-nil Response with a non-nil error only occurs when CheckRedirect fails, and even then the returned Response.Body is already closed.
https://golang.org/pkg/net/http/#Client.Do
resp, err := http.Get("http://xxxx.xxx")
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
这种方式是ok的,不必考虑resp为非nil的情况(出现重定向错误),这种情况下body已经被close
src/runtime/HACKING.md
The scheduler's job is to match up a G (the code to execute), an M (where to execute it), and a P (the rights and resources to execute it).
All g
, m
, and p
objects are heap allocated, but are never freed,
so their memory remains type stable. As a result, the runtime can
avoid write barriers in the depths of the scheduler.
打印结构体
%v``%+v``%#v
的区别针对结构体 %v 打印字段的值 %+v 打印字段的名字和字段的值 %#v 按照go中结构体的格式打印(打印结构体的名字,字段的名字和值) 如果字段是指针,值就是指针地址。 可以给结构体实现一个 String() string方法自定义打印的格式(从而打印指针对应的内容)。对%v和%+v生效,对%#v不生效。
实现了String()string 意味着实现了fmt.Stringer。fmt包中
%v
和%+v
会检查参数实现了error或者Stringer,从而调用errror()或者String()。%#v
则需要实现 GoString()string 方法来自定义。实现 fmt.Formatter 可做到更加灵活的格式控制。github.com/pkg/errors 就是用这种方式输出调用栈。可获取到 fmt.State 进行写,verb 判断占位符。