gobomb / myDoc

The documents and notes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

go

gobomb opened this issue · comments

打印结构体%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 判断占位符。

限制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())
}

ref: https://my.oschina.net/xlplbo/blog/682884

grpcui -plaintext -bind 0.0.0.0 -proto proto/orca.proto 10.10.13.7:1400

grpc 调试工具(类似postman之于http)

https://github.com/fullstorydev/grpcui

go mod 系列博客阅读笔记

https://blog.golang.org/using-go-modules

  1. Starting in Go 1.13, module mode will be the default for all development.

  2. The indirect comment indicates a dependency is not used directly by this module, only indirectly by other module dependencies. 

  3. 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.

  4. go buildgo test, and other package-building commands add new dependencies to go.mod as needed.

    go mod tidy removes unused dependencies.

  5. Note that when go mod tidy adds a requirement, it adds the latest version of the module.

  6. 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.

  7. Sometimes, maintaining backwards compatibility can lead to awkward APIs. That's OK. An imperfect API is better than breaking users' existing code.

  8. If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.

  9. 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.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

自动生成单元测试模板

  1. A deferred function's arguments are evaluated when the defer statement is evaluated. defer函数的参数赋值发生在defer语句赋值之时(发生了复制,所以复制的值取决于defer函数定义的时候的值)
  2. Deferred function calls are executed in Last In First Out order after the surrounding function returns.
  3. Deferred functions may read and assign to the returning function's named return values.(没有发生复制,而是使用了闭包环境的变量)

The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values.

https://blog.golang.org/defer-panic-and-recover

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

https://golang.org/doc/faq#nil_error

for _, v := range values{} v使用的都是同一个变量

https://golang.org/doc/faq#closures_and_goroutines

Go has no 'reference types'

golang/go@b34f055

  • byte 等同于int8,常用来处理ascii字符
  • rune 等同于int32,常用来处理unicode或utf-8字符
	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

mholt/curl-to-go#6

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.