前言

记录Golang的一些常用包的使用。

日期覆盖
~ 2021-06-11os, io, ioutil, runtime
~2021-06-13context, reflect

os

os - 系统API
  • 更改当前工作目录

    1
    func Chdir(dir string) error
  • 获取当前目录(pwd)

    1
    func  Getwd()(dir string, err error)
  • 更改文件权限 (chmod)

    1
    func Chmod(name string, mode FileMode) error
  • 更改拥有者 (chown)

    1
    func Chown(name string,uid,gid int) error
  • 更改文件的访问时间和修改时间

    1
    func Chtimes(name string, atime time.Time, mtime time.Time)error
  • 清除所有环境变量

    1
    func Clearenv()
  • 返回所有环境变量

    1
    func Environ()[]string
  • 系统退出 执行Exit, defer函数不会执行

    1
    func Exit(code int)
  • 用mapping函数定义的规则替换字符串中的${var} 或者 $var

    1
    func Expand(s string, mapping func(string)string )string
  • ExpandEnv根据当前环境变量的值来替换字符串中的${var}或者$var。如果引用变量没有定义,则用空字符串替换。

    1
    func ExpandEnv(s string)string
  • 获取指定环境变量的值,无则空

    1
    func Getenv(key string)string
  • 获取调用者用户/用户组id/用户组

    1
    2
    3
    func Geteuid() int
    func Getgid() int
    func Getgroups()([]int, error)
  • 获取底层系统内存页的数量

    1
    func Getpagesize() int
  • 获取进程id/父进程id

    1
    2
    func Getpid() int
    func Getppid() int
  • 获取主机名

    1
    func Hostname()(name string, err error)
  • 返回布尔值, 它指明err错误是否报告了一个文件或者目录已经存在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func IsExist(err error)bool
    // demo
    func Exist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil || os.IsExist(err)
    }

    // -----

    func IsNotExist(err error)bool
  • 判断入参是否是路径分割符号 比如(‘/‘)

    1
    func IsPathSeparator(c unit8) bool
  • 创建一个新目录,若存在,则报错

    1
    func Mkdir(name string, perm Filemode) error
  • 创建多级目录, 若不存在,则创建(包括父级和子级),不存在也不会报错

    1
    func MkdirAll(path string, perm Filemode) error
  • 删除文件或者目录 / 删除多层目录及子文件

    1
    2
    3
    func Remove(name string) error

    func RemoveAll(path string) error
  • 重命名,如果文件不存在,报错

    1
    func Rename(oldpath, newpath string) error
  • 查看是否是同一个文件, 入参只能是 os.stat 的 返回

    1
    func SameFile(f1, f2 FileInfo) bool
  • 设定环境变量

    1
    func Setenv(key, value string) error
  • 按照指定长度将文件截断

    1
    func Truncate(name string, size int64) error
  • 获取FileInfo信息

    1
    func Stat(name string)(fi FileInfo, err error)
os - 文件API
1
2
3
4
5
6
7
8
type FileInfo interface{
Name() string
Size() int64
Mode() FileMode
ModTime() time.Time // 更改时间
IsDir() bool
Sys() interface // 基础数据源
}
  • 创建一个文件 (File: 打开的文件描述符), 文件mode0666(读写),如果文件已经存在,会创建新文件覆盖。等同于 OpenFile(name string, O_CREATE,0666)

    1
    func Create(name string)(file *File, err error)
  • 指定文件权限和打开方式 打开或者创建文件

    1
    func OpenFile(name string, flag int, perm FileMode)(file *File, err error)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const (
    O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
    O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
    O_RDWR int = syscall.O_RDWR // 读写模式打开文件
    O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
    O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
    O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
    O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
    O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
    )
  • O_RDONLY:只读模式(read-only)

  • O_WRONLY:只写模式(write-only)

  • O_RDWR:读写模式(read-write)

  • O_APPEND:追加模式(append)

  • O_CREATE:文件不存在就创建

  • O_EXCL:与 O_CREATE 一起用,构成一个新建文件的功能,它要求文件必须不存在

  • O_SYNC:同步方式打开,即不使用缓存,直接写入硬盘

  • O_TRUNC:打开并清空文件

    至于操作权限perm,除非创建文件时才需要指定,不需要创建新文件时可以将其设定为0.虽然go语言给perm权限设定了很多的常量,但是习惯上也可以直接使用数字,如0666(具体含义和Unix系统的一致).

  • 返回一对连接的文件,从r中读取写入w中的数据,返回文件和该过程中的错误

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    func Pipe()(r *File, w *File, err error)

    //demo

    func main(){
    f, w, err := os.Pipe()
    if err != nil{
    log.Fatal(err)
    }
    w.WriteString("hello, world")
    s := make([]byte, 20)
    n, _ := r.Read(s)
    fmt.Println(string(s[:n]))
    }
  • 更改工作目录 / 文件权限 / 文件所有者 / 关闭(和 defer配合使用 )

    1
    2
    3
    4
    5
    6
    7
    func (f *File)Chdir() error

    func (f *File)Chmod() error

    func (f *File)Chown() error

    func (f *File)Close() error
  • 获取文件句柄/文件描述符

    1
    func (f *File)Fd() unitptr
  • 获取文件名字 == file.Stat().Name()

    1
    func (f *File)Name() string
  • 将len(b)的数据从f中读取到b中,如果无错,则返回n和nil,否则返回读取的字节数n以及响应的错误

    1
    func (f *File)Read(b []byte)(n int, err error)
  • Read+指定起始读取位置offset

    1
    func (f *File) ReadAT(b []byte, off int64)(n int, err error)
  • 读取指定目录下最多n个Fileinfo / fileinfo的name

    1
    2
    3
    func Readdir(n int)(fi []FileInfo, err error)

    func Readdirnames(n int)(names []string, err error)
  • 设置下一次读写操作的偏移量offset, whence [0:原始位置, 1:相对于当前偏移量, 2:相对于文件结尾 ], 返回新的偏移量和错误

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    func (f *File)Seek(offset int64, whence int)(ret int64, err error)

    // demo
    func main(){
    s := make([]byte, 10)
    file, _ := os.Open("tmp.txt")
    defer file.Close()
    file.Seek(-12, 2) // 倒数12的位置开始操作
    n, _ := file.Read(s)
    fmt.Println(string(s[:n]))
    }
  • 获取文件描述信息,大小,名字等 == os.Stat(filename string)

    1
    func (f *File) Stat()(fi Fileinfo, err error)
  • 同步操作,将内存中的内容写入磁盘

    1
    func (f *File)Sync()err error
os - 进程API

// TODO

io

Golang的 io包提供了对 I/O原语的基本接口。(原语是操作系统的核心,内核或微核提供核外调用的过程或函数称为原语(primitive)。由若干条指令组成,来完成一定功能的过程,执行必须过程连续,不允许被中断)

io包 包装原语已有的实现,成为共享的公共接口。除非特别声明,否则这些接口时非并发安全的。

从方法和接口两个方面记录 io 包的常用点。(并不全面,全部内容地址: https://studygolang.com/pkgdoc)

错误

  • EOF, 当读取正常进行到终点,返回EOF,表示读取完成。

    1
    var EOF = errors.New("EOF")

interface

  • 读取接口, Read方法读取len(p)的字节数写入p,返回写入的字节数和遇到的错误

    1
    2
    3
    type Reader interface {
    Read(p []byte)(n int, err error)
    }
  • 写入接口, Write方法将len(p)字节从p写入底层数据流,返回写入的字节数和遇到的错误

    1
    2
    3
    type Writer interface {
    Write(p []byte)(n int, err error)
    }
  • 关闭接口

    1
    2
    3
    type Closer interface {
    Close() error
    }
  • 偏移量接口, 读写操作的偏移量offset,校准点whence,0:起始位置,1:相对于当前位置,2:文件结尾,返回新的偏移位置和遇到的错误

    1
    2
    3
    type Seeker interface {
    Seek(offset int64, whence int)(int64, error)
    }
  • 组合接口

    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

    type ReadCloser interface{
    Reader()
    Closer()
    }

    type ReadSeeker interface{
    ...
    }

    type WriteCloser interface{
    ...
    }

    type WriteSeeker interface{
    ...
    }

    type ReadWriter interface {
    ...
    }

    type ReadWriteCloser interface {
    ...
    }

    type ReadWriteSeeker interface {
    ...
    }
  • 指定偏移量 读 / 写, 返回 读 /写的字节数和遇到的错误

    1
    2
    3
    4
    5
    6
    7
    type ReaderAt interface {
    ReadAt(p []byte, off int64)(n int, err error)
    }

    type WriterAt interface {
    WriteAt(p []byte, off int64)(n int, err error)
    }
  • 读取单个字节并返回,没有可读取字节返回错误

    1
    2
    3
    type ByteReader interface{
    ReadByte()(c byte, err error)
    }
  • 读取单个utf8编码的字符(rune), 返回该字符及字节长度,无有效字符返回错误

    1
    2
    3
    tyep RuneReader interface {
    ReadRune()(r rune, size int, err error)
    }
  • 写入单个字节

    1
    2
    3
    type ByteWriter interface {
    WriteByte(c byte) error
    }
  • 从Reader读 / 写入 Writer

    1
    2
    3
    4
    5
    6
    7
    type ReaderFrom interface {
    ReadFrom(r Reader)(n int64, err error)
    }

    type WriterTo interface {
    WriteTo(w Writer) (n int64, err error)
    }
  • 从R中读取数据,限制最多字节数

    1
    2
    3
    4
    5
    6
    7
    8
    type LimitedReader struct{
    R Reader
    N int64
    }

    func LimitReader(r Reader, n int64) Reader

    func (*LimitedReader) Read

function

  • 返回将r读取的数据写入w的Reader接口。所有对r的读取都会无缓冲的写入w

    1
    func TeeReader(r Reader, w Writer) Reader
  • 依次读取多个Reader接口,所有的输入流读取完毕,返回EOF

    1
    func MultiReader(readers ...Reader) Reader
  • 依次写入多个Writer接口

    1
    func MultiWriter(writers ...Writer) Writer
  • 将src的 数据 / n个字节的数据 复制到dst,直到EOF或错误,返回复制的字节数和错误

    1
    2
    3
    func Copy(dst Writer, src Reader)(written int64, err error)

    func CopyN(dst Writer, src Reader, n int64)(written int64, err error)
  • 从r读取至少min字节填充至buf。返回写入的字节数和错误。如果min>len(buf), 返回ErrShorBuffer

    1
    func ReadAtLeast(r Reader, buf []byte, min int)(n int, err error)
  • 从r中读取全部字节填充至buf

    1
    func ReadFill(r Reader, buf []byte)(n int, err error)
  • 将字符串s写入w中。如果w已经实现了WriteString,函数会直接调用此方法

    1
    func WriteString(w Writer, s string)(n int, err error)

io/ioutil

  • 返回ReadCloser接口

    1
    func NopCloser(r io.Reader) io.ReadCloser
  • 读取全部数据

    1
    func ReadAll(r io.Reader)([]byte, error)
  • 读取指定文件全部数据

    1
    func ReadFile(filename string)([]byte, error)
  • 向指定文件写入数据,不存在则按照权限创建,否则写入之前先清空内容

    1
    func WriteFile(filename string, data []byte, perm os.FileMode)error
  • 返回指定的目录的目录信息有序列表

    1
    func ReadDir(dirname string)([]os.FileInfo, error)
  • 在dir目录创建一个使用profix前缀的临时文件夹,返回文件夹路径和错误

    1
    func TempDir(dir, profix string)(name string, err error)
  • 在dir目录创建一个使用profix前缀的临时文件,读写模式打开并返回os.File指针

    1
    func TempFile(dir, prefix string)(f *os.File, err error)

runtime

runtime包提供了go运行时环境的交互操作,比如控制协程。

runtime特性待详细补充

常量

  • 编译工具链 Compiler

    1
    2
    const Compiler = "gc"
    // 已知工具链为 gc 和 gccgo
  • 可执行程序的目标处理器架构 GOARCH

    1
    2
    const GOARCH string = theArch
    // theArch: 386 / amd64 / arm
  • 可执行程序的目标操作系统 GOOS

    1
    2
    const GOOS string = theGoos
    // thGoos: darwin / linux / ...等

变量

  • var MemProfileRate int = 512 * 1024
    
    // MemProfileRate控制会在内存profile里记录和报告的内存分配采样频率
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17



    #### function (不全)

    - 返回GOROOT / go版本 / 逻辑CPU个数 / 设置同时执行的最大CPU数,并返回之前的设置 / 执行垃圾回收

    ```go
    func GOROOT() string

    func Version() string

    func NumCPU() int

    func GOMAXPROCS(n int) int

    func GC()
  • 调用栈踪迹写入 buf 并返回写入的字节数,all==true,会在写入当前go协程的踪迹信息后,将其他协程的调用栈踪迹也写入

    1
    func Stack(buf []byte, all bool) int
  • 当前协程调用栈执行的函数文件和行号信息,skip为上溯的栈帧数,返回调用栈标识符,文件名,行号

    1
    func Caller(skip int)(pc uintptr, file string,line int, ok bool)
  • 当前协程调用栈上的调用栈的标识符写入pc,返回写入的个数。0:Callers自身调用栈,1:Callers自身所在的调用栈

    1
    func Callers(skip int, pc []uintptr)int
  • 当前进程执行的cgo调用次数 / 当前进程存在的协程数

    1
    2
    3
    func NumCgoCall() int64

    func NumGoroutine() int
  • 终止当前协程,defer函数依然会执行 / 当前协程让出处理器

    1
    2
    3
    func Goexit()

    func Gosched()

context

goroutine是golang 的并发实现。golang实现的服务器中,需要为每一个HTTP创建一个goroutine来并发处理请求,每一个goroutine又会创建多个groutine来访问数据库等操作。那么当该请求被终止或者超时,需要一种机制来通知所有的衍生groutine来优雅退出。context就是官方提供的一种方案。

context包提供上下文机制在goroutine之间传递deadline,cancellation signals(取消信号)或者其他的请求相关的信息。

基本的使用流程是:

  1. 服务器程序为每个接收的请求创建一个Context实例(根context, 通过 context.Background()方法创建)
  2. 衍生的goroutine接收根context的一个派生Context对象(比如context.WithCancel创建的子context)
  3. goroutine通过context.Done()方法监听取消信号,func Done() <- chan struct{}是一个通信操作,阻塞gogroutine,直到收到信号解除阻塞
  4. 当一个Context被取消,该Context衍生出的context也会被取消。

Context 接口类型

1
2
3
4
5
6
type Context interface{
Done() <- chan struct{}
Deadline() (deadline timet.Time, ok bool)
Err() error
Value(key interface{}) interface{}
}
1. Done() <- chan struct{}

该方法返回一个只读的chnanel,阻塞当前goroutine代码,直到收到解除阻塞的信号:

  1. WithCancel 创建的 context,cancelFunc 被调用。该 context 以及派生子 context 的 Done channel 都会收到取消信号
  2. WithDeadline 创建的 context,deadline 到期
  3. WithTimeout 创建的 context,timeout 到期

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func Stream(ctx context.Context, out chan <- value) error{
for {
v, err := DoSomethine(ctx)
if err != nil{
return nil
}

select {
case <-ctx.Done():
return ctx.Err()
case out <- v:
fmt.Print()
}
}
}
2. Deadline() (deadline timet.Time, ok bool)

WithDeadline 方法会给 context 设置 deadline,到期自动发送取消信号。调用 Deadline() 返回 deadline 的值

3. Err() error

如果 Done 的 channel 被关闭了, Err 函数会返回一个 error,说明错误原因:

  1. 如果 channel 是因为被取消而关闭,打印 canceled;
  2. 如果 channel 是因为 deadline 到时了,打印 deadline exceeded。
4. Value(key interface{}) interface{}

返回由 WithValue 关联到 context 的值

创建根Context

有两种方法创建根 Context:

  1. context.Background()
  2. context.TODO()

根 context 不会被 cancel。这两个方法只能用在最外层代码中,比如 main 函数里。一般使用 Background() 方法创建根 context。TODO() 用于当前不确定使用何种 context,留待以后调整。

创建派生context

一个 Context 被 cancel,那么它的派生 context 都会收到取消信号(表现为 context.Done() 返回的 channel 收到值)。有四种方法派生 context :

  1. func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
  2. func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
  3. func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
  4. func WithValue(parent Context, key, val interface{}) Context
1. WithCancel

最常用的派生 context 方法。该方法接受一个父 context。父 context 可以是一个 background context 或其他 context。返回的 cancelFunc,如果被调用,会导致 Done channel 关闭。因此,绝不要把 cancelFunc 传给其他方法

2.WithDeadline

该方法会创建一个带有 deadline 的 context。当 deadline 到期后,该 context 以及该 context 的可能子 context 会受到 cancel 通知。另外,如果 deadline 前调用 cancelFunc 则会提前发送取消通知

3. WithTimeout

与 WithDeadline 类似。创建一个带有超时机制的 context。

4. WithValue

WithValue 方法创建一个携带信息的 context,可以是 user 信息、认证 token等。该 context 与其派生的子 context 都会携带这些信息。

WithValue 方法的第二个参数是信息的唯一 key。该 key 类型不应对外暴露,为了避免与其他包可能的 key 类型冲突。所以使用 WithValue 也应像下面例子的方式间接调用 WithValue。

WithValue 方法的第三个参数即是真正要存到 context 中的值。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package user

import "context"

type User struct{
...
}

type key int // 私有key,不对外暴漏
type userKey key // user 的key, 不对外暴漏

func NewContext(ctx context.Context, u *User)context.Context{
return context.WithValue(ctx, userKey, u)
}

func FromContext(ctx context.Context)(*User, bool){
u, ok := ctx.Value(userKye).(*User)
return u, ok
}

functions

  • 最外层(main)创建 Context, Background方法生成空context, 不能被cancel, 无value, 无deadline.

    1
    func Background() Context
  • TODO创建Context, 当不清楚具体需要什么context时调用此方法创建

    1
    func TODO() context
  • WithCancel 接收context, /

    WithDeadline接收context和一个deadline(比如time.Now().Add(50*time.Millisecond)), /

    WithTimeout接收context和一个时间周期(比如 50*time.Millisecond) , /

返回子级context包含一个新的 Done channel和一个Cancel方法。当该方法被调用或者父级context Done channel被关闭,这个新生成的Done channel 随之关闭

WithValue 接收context, key, 和 interface类型值, 返回Context

1
2
3
4
5
6
7
func WithCancel(parent context)(ctx context, cancel CancelFunc)

func WithDeadline(parent context, deadline time.Time)(Context, CancelFunc)

func WithTimeout(parent context, timeout time.Duration)(Context, CancelFunc)

func WithValue(parent context,key,val interface{}) Context

reflect

Golang 是静态类型语言,在编译时就能确定变量类型(比如 var a int), 运行时才知道的变量类型叫做动态类型。(比如 var a interface{}; a = 10)

反射,就是帮助开发者在运行时获取变量的类型和值的官方标准库。reflect库可以帮助我们在运行时检查,修改创建变量,函数和结构。

什么时候会需要反射?比如将文件或网络请求数据映射到变量中,也许试图创建一个适用于不同类型的工具等等。

  • 当Value类型值调用不支持的方法时,导致 ValueError

    1
    2
    3
    4
    5
    6
    type ValueError struct{
    Method string
    Kind Kind
    }

    func(*ValueError)Error() string
  • Kind代表 Type类型值 表示的具体分类,0值表示非法分类

    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
    type Kind uint

    const(
    Invalid Kind = iota
    Bool
    Int
    Int8
    Int16
    Int32
    Int64
    Uint
    Uint8
    Uint16
    Uint32
    Uint64
    Uintptr
    Float32
    Float64
    Complex64
    Complex128
    Array
    Chan
    Func
    Interface
    Map
    Ptr
    Slice
    String
    Struct
    UnsafePointer
    )

    func (k kind) String() string
  • 方法

    1
    2
    3
    4
    5
    6
    7
    type Method struct{
    Name string // 方法名
    PkgPath string // 非导出字段的包路径, PkgPath + Name 可以指定一个方法
    Type Type // 方法类型
    Func Value // 方法的值
    Index int // 用于Type.Method的索引
    }
  • Type类型用来表示一个go类型。可以通过 TypeOf()获得,

    需要注意的是,不是所有的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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    type Type interface {
    // Kind返回该接口的具体分类
    Kind() Kind
    // Name返回该类型在自身包内的类型名,如果是未命名类型会返回""
    Name() string
    // PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64"
    // 如果类型为内建类型(string, error)或未命名类型(*T, struct{}, []int),会返回""
    PkgPath() string
    // 返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64")
    // 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。
    String() string
    // 返回要保存一个该类型的值需要多少字节;类似unsafe.Sizeof
    Size() uintptr
    // 返回当从内存中申请一个该类型值时,会对齐的字节数
    Align() int
    // 返回当该类型作为结构体的字段时,会对齐的字节数
    FieldAlign() int
    // 如果该类型实现了u代表的接口,会返回真
    Implements(u Type) bool
    // 如果该类型的值可以直接赋值给u代表的类型,返回真
    AssignableTo(u Type) bool
    // 如该类型的值可以转换为u代表的类型,返回真
    ConvertibleTo(u Type) bool
    // 返回该类型的字位数。如果该类型的Kind不是Int、Uint、Float或Complex,会panic
    Bits() int
    // 返回array类型的长度,如非数组类型将panic
    Len() int
    // 返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map、Ptr或Slice,会panic
    Elem() Type
    // 返回map类型的键的类型。如非映射类型将panic
    Key() Type
    // 返回一个channel类型的方向,如非通道类型将会panic
    ChanDir() ChanDir
    // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic
    NumField() int
    // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
    Field(i int) StructField
    // 返回索引序列指定的嵌套字段的类型,
    // 等价于用索引中每个值链式调用本方法,如非结构体将会panic
    FieldByIndex(index []int) StructField
    // 返回该类型名为name的字段(会查找匿名字段及其子字段),
    // 布尔值说明是否找到,如非结构体将panic
    FieldByName(name string) (StructField, bool)
    // 返回该类型第一个字段名满足函数match的字段,布尔值说明是否找到,如非结构体将会panic
    FieldByNameFunc(match func(string) bool) (StructField, bool)
    // 如果函数类型的最后一个输入参数是"..."形式的参数,IsVariadic返回真
    // 如果这样,t.In(t.NumIn() - 1)返回参数的隐式的实际类型(声明类型的切片)
    // 如非函数类型将panic
    IsVariadic() bool
    // 返回func类型的参数个数,如果不是函数,将会panic
    NumIn() int
    // 返回func类型的第i个参数的类型,如非函数或者i不在[0, NumIn())内将会panic
    In(i int) Type
    // 返回func类型的返回值个数,如果不是函数,将会panic
    NumOut() int
    // 返回func类型的第i个返回值的类型,如非函数或者i不在[0, NumOut())内将会panic
    Out(i int) Type
    // 返回该类型的方法集中方法的数目
    // 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法;
    // 匿名字段导致的歧义方法会滤除
    NumMethod() int
    // 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic
    // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
    // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
    Method(int) Method
    // 根据方法名返回该类型方法集中的方法,使用一个布尔值说明是否发现该方法
    // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
    // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
    MethodByName(string) (Method, bool)
    // 内含隐藏或非导出方法
    }
  • 返回接口中保存的值的类型(Type), TypeOf(nil) 返回nil

    1
    func TypeOf(i interface{}) Type
  • 返回类型t的指针类型

    1
    2
    3
    4
    5
    6
    7
    8
    func PtrTo(t Type) Type

    //
    // a := 100
    // at := reflect.TypeOf(a)
    // fmt.Println(at) // int
    // atPtr := reflect.PtrTo(at)
    // fmt.Println(atPtr) // *int
  • 返回类型的切片的类型

    1
    2
    3
    4
    5
    6
    func SliceOf(t Type) Type

    // a := 100
    at := reflect.TypeOf(a)
    atPtr := reflect.SliceOf(at)
    fmt.Println(atPtr) // []int
  • 返回健类型为key, 值类型为elem的映射类型。

    1
    func MapOf(key, elem Type) Type
  • 返回类型为t, 方向为dir的通道类型。运行时GC强制将通道的元素类型大小限定为64Knb, 如果大于等于该限制,触发panic

    1
    func ChanOf(dir chanDir, t Type) Type
  • Value 为go值提供反射接口, 由 ValueOf()获取

    1
    2
    3
    type Value struct{
    // 内含隐藏或非导出字段
    }
  • 返回一个初始化为i接口 保管的具体值,ValueOf(nil)返回Value 零值

    1
    func ValueOf(i interface{}) Value
  • 返回一个持有类型typ 的零值的Value, 持有零值的Value和Value零值是两回事,Value零值表示不持有任何值,例如 Zero(TypeOf(42)) 返回Kind是int, 值为0的Value。

    1
    func Zero(typ Type) Value
  • 返回一个Value类型值,该值持有一个指向类型为typ的新申请的零值的指针,返回值为Type的PtrTo(typ)

    1
    func New(typ Type) Value
  • NewAt返回一个Value类型值,该值持有一个指向类型为typ、地址为p的值的指针

    1
    func NewAt(typ Type, p unsafe.Pointer) Value
  • 返回持有v持有的指针指向的值的Value。如果v持有nil指针,会返回Value零值;如果v不持有指针,会返回v。

    1
    func Indirect (v Value) Value
  • MakeSlice创建一个新申请的元素类型为typ,长度len容量cap的切片类型的Value值。

    MakeMap创建一个特定映射类型的Value值。

    MakeChan创建一个元素类型为typ、有buffer个缓存的通道类型的Value值。

    1
    2
    3
    4
    5
    func MakeSlice(typ Type, len, cap int) Value

    func MakeMap(typ Type) Value

    func MakeChan(typ Type, buffer int)Value
  • MakeFunc

    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
    func MakeFunc(typ Type, fn func(args []Value)(results []Value) )Value

    // 示例:
    swap := func(in []reflect.Value) []reflect.Value {
    return []reflect.Value{in[1], in[0]}
    }

    makeSwap := func(fptr interface{}) {
    fn := reflect.ValueOf(fptr).Elem()
    // Make a function of the right type.
    v := reflect.MakeFunc(fn.Type(), swap)
    // Assign it to the value fn represents.
    fn.Set(v)
    }
    // Make and call a swap function for ints.
    var intSwap func(int, int) (int, int)
    makeSwap(&intSwap)
    fmt.Println(intSwap(0, 1))
    // Make and call a swap function for float64s.
    var floatSwap func(float64, float64) (float64, float64)
    makeSwap(&floatSwap)
    fmt.Println(floatSwap(2.72, 3.14))

    // 输出:
    1 0
    3.14 2.72
  • 向切片类型的Value值s中添加值,x等Value值持有的值必须能直接赋值给s持有的切片的元素类型

    1
    2
    3
    func Append(s Value, x ...Value) Value

    func AppendSlice(s, t Value) Value
  • 检查v是否持有一个值,如果v是Value零值返回假, Value零值的情况下除了IsValid,String,Kind其他情况都会panic

    1
    func (Value)IsValid() bool
  • IsNil检查v持有的值是否为nil, v持有值得分类必须是channel,func,interface,reflect,ptr,slice之一。否则panic。

    1
    func (v Value)IsNil() bool
  • 返回V持有值的分类, v是value零值,返回invalid / 返回v持有值的type

    1
    2
    3
    func (Value)Kind() Kind

    func (Value)Type() Type
  • 将v持有值转换为类型为t的值,返回该值的Value封装,如果转换规则不支持这种转换,导致panic

    1
    func (v Value) Convert(t Type) Value
  • Elem 返回v持有的接口或者指针 保管/指向 的值的Value封装。非接口或者指针则Panic。如果v持有值为nil, 返回Value零值。

    返回v持有的布尔值,非布尔值panic

    返回v持有的有符号整数,非有符号整数panic

    如果v持有值的类型不能无溢出的表示x,会返回真。如果v的Kind不是Int、Int8、Int16、Int32、Int64会panic

    。。。

    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
    func (Value) Elem() Value

    func (Value) Bool() bool

    func (Value) Int() int64

    func (Value)OverflowInt(x int64) bool

    func (Value)Uint() uint64

    func (v Value) OverflowUint(x uint64) bool

    func (v Value) Float() float64

    func (v Value) Complex() complex128

    func (v Value) OverflowComplex(x complex128) bool

    func (v Value) Pointer() uintptr

    func (v Value) Bytes() []byte

    func (v Value) String() string // :vKindString时,返回该字符串;vKind不是String时也不会panic而是返回格式为"<T value>"的字符串,其中Tv持有值的类型

    func (v Value) InterfaceData() [2]uintptr

    func (v Value) Slice3(i, j, k int) Value // 是Slice的3参数版本,返回v[i:j:k] ;如果vKind不是ArraySliceStringpanic。如果v是一个不可寻址的数组,或者索引出界,也会panic

    func (v Value) Cap() int // 返回v持有值的容量,如果vKind不是ArrayChanSlicepanic

    func (v Value) Len() int // 返回v持有值的长度,如果vKind不是ArrayChanSliceMapStringpanic


    func (v Value) Index(i int) Value // 返回v持有值的第i个元素。如果vKind不是ArrayChanSliceString,或者i出界,会panic

    func (v Value) MapIndex(key Value) Value // 返回v持有值里key持有值为键对应的值的Value封装。如果vKind不是Mappanic。如果未找到对应值或者v持有值是nil映射,会返回Value零值。key的持有值必须可以直接赋值给v持有值类型的键类型。


    func (v Value) MapKeys() []Value // 返回一个包含v持有值中所有键的Value封装的切片,该切片未排序。如果vKind不是Mappanic。如果v持有值是nil,返回空切片(非nil)。



  • 返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic

    1
    func (v Value) NumField() int
  • 返回结构体的第i个字段(的Value封装)。如果v的Kind不是Struct或i出界会panic

    1
    func (v Value) Field(i int) Value
  • 返回索引序列指定的嵌套字段的Value表示,等价于用索引中的值链式调用本方法,如v的Kind非Struct将会panic

    1
    func (v Value) FieldByIndex(index []int) Value
  • 返回该类型名为name的字段(的Value封装)(会查找匿名字段及其子字段),如果v的Kind不是Struct会panic;如果未找到会返回Value零值。

    1
    func (v Value) FieldByName(name string) Value
  • 返回该类型第一个字段名满足match的字段(的Value封装)(会查找匿名字段及其子字段),如果v的Kind不是Struct会panic;如果未找到会返回Value零值。

    1
    func (v Value) FieldByNameFunc(mathc func(string) bool) Value
  • 通道相关

    1
    2
    3
    4
    5
    6
    7
    8
    9
    func (v Value) Recv() (x Value, ok bool) // 方法从v持有的通道接收并返回一个值(的Value封装)。如果vKind不是Chanpanic。方法会阻塞直到获取到值。如果返回值x对应于某个发送到v持有的通道的值,ok为真;如果因为通道关闭而返回,xValue零值而ok为假

    func (v Value) TryRecv() (x Value, ok bool) // TryRecv尝试从v持有的通道接收一个值,但不会阻塞。如果vKind不是Chanpanic。如果方法成功接收到一个值,会返回该值(的Value封装)和true;如果不能无阻塞的接收到值,返回Value零值和false;如果因为通道关闭而返回,返回值x是持有通道元素类型的零值的Valuefalse

    func (v Value) Send(x Value) // 方法向v持有的通道发送x持有的值。如果vKind不是Chan,或者x的持有值不能直接赋值给v持有通道的元素类型,会panic

    func (v Value) TrySend(x Value) bool // TrySend尝试向v持有的通道发送x持有的值,但不会阻塞。如果vKind不是Chanpanic。如果成功发送会返回真,否则返回假。x的持有值必须可以直接赋值给v持有通道的元素类型

    func (v Value) Close() // 关闭v持有的通道,如果vKind不是Chanpanic
  • Call方法使用输入的参数in调用v持有的函数。例如,如果len(in) == 3,v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果v的Kind不是Func会panic。它返回函数所有输出结果的Value封装的切片

    1
    func (v Value) Call(in []Value) []Value
  • CallSlice调用v持有的可变参数函数,会将切片类型的in[len(in)-1](的成员)分配给v的最后的可变参数。例如,如果len(in) == 3,v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值,可变参数函数的可变参数位置提供一个切片并跟三个点号代表”解切片”)。如果v的Kind不是Func或者v的持有值不是可变参数函数,会panic。它返回函数所有输出结果的Value封装的切片。和go代码一样,每一个输入实参的持有值都必须可以直接赋值给函数对应输入参数的类型

    1
    func (v Value) CallSlice(in []Value) []Value
  • 返回v持有值的方法集的方法数目

    1
    func (v Value) NumMethod() int
  • 返回v持有值类型的第i个方法的已绑定(到v的持有值的)状态的函数形式的Value封装。返回值调用Call方法时不应包含接收者;返回值持有的函数总是使用v的持有者作为接收者(即第一个参数)。如果i出界,或者v的持有值是接口类型的零值(nil),会panic。

    1
    func (v Value) Method(i int) Value
  • 返回v的名为name的方法的已绑定(到v的持有值的)状态的函数形式的Value封装。返回值调用Call方法时不应包含接收者;返回值持有的函数总是使用v的持有者作为接收者(即第一个参数)。如果未找到该方法,会返回一个Value零值。

    1
    func (v Value) MethodByName(name string) Value
  • 返回是否可以获取v持有值的指针。可以获取指针的值被称为可寻址的。如果一个值是切片或可寻址数组的元素、可寻址结构体的字段、或从指针解引用得到的,该值即为可寻址的

    1
    func (v Value) CanAddr() bool
  • 函数返回一个持有指向v持有者的指针的Value封装。如果v.CanAddr()返回假,调用本方法会panic。

    返回指向v持有数据的地址的指针(表示为uintptr)以用作高级用途,如果v不可寻址会panic。

    1
    2
    3
    func (v Value) Addr() Value

    func (v Value) UnsafeAddr() uintptr
  • 如果CanInterface返回真,v可以不导致panic的调用Interface方法。

    返回v当前持有的值(表示为/保管在interface{}类型),等价于:var i interface{} = (v’s underlying value)

    1
    2
    3
    4
    func (v Value) CanInterface() bool

    func (v Value) Interface() (i interface{})

  • 如果v持有的值可以被修改,CanSet就会返回真。只有一个Value持有值可以被寻址同时又不是来自非导出字段时,它才可以被修改

    1
    func (v Value) CanSet() bool
  • 修改相关

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    func (v Value) SetBool(x bool)  // 设置v的持有值。如果vKind不是Bool或者v.CanSet()返回假,会panic

    func (v Value) SetInt(x int64)

    func (v Value) SetUint(x uint64)

    func (v Value) SetFloat(x float64)

    func (v Value) SetComplex(x complex128)

    func (v Value) SetBytes(x []byte)

    func (v Value) SetString(x string)

    func (v Value) SetPointer(x unsafe.Pointer)

    func (v Value) SetCap(n int)

    func (v Value) SetLen(n int)

    func (v Value) SetMapIndex(key, val Value) //用来给v的映射类型持有值添加/修改键值对,如果valValue零值,则是删除键值对。如果vKind不是Map,或者v的持有值是nil,将会panickey的持有值必须可以直接赋值给v持有值类型的键类型。val的持有值必须可以直接赋值给v持有值类型的值类型
  • 将v的持有值修改为x的持有值。如果v.CanSet()返回假,会panic。x的持有值必须能直接赋给v持有值的类型。

    1
    func (v Value) Set (x Value)
  • 将src中的值拷贝到dst,直到src被耗尽或者dst被装满,要求这二者都是slice或array,且元素类型相同。

    1
    func Copy(dst, src Value) int
  • 用来判断两个值是否深度一致:除了类型相同;在可以时(主要是基本类型)会使用==;但还会比较array、slice的成员,map的键值对,结构体字段进行深入比对。map的键值对,对键只使用==,但值会继续往深层比对。DeepEqual函数可以正确处理循环的类型。函数类型只有都会nil时才相等;空切片不等于nil切片;还会考虑array、slice的长度、map键值对数

    1
    func DeepEqual(a1, a2 interface{}) bool