源码阅读苦练基本功Golang内置函数分析
Posted 在路上的德尔菲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码阅读苦练基本功Golang内置函数分析相关的知识,希望对你有一定的参考价值。
Golang package builtin
中内置函数我分为两部分介绍,第一部分为基础类型,第二部分为包含函数、接口,较复杂一些
第一部分
// bool is the set of boolean values, true and false.
type bool bool
// true and false are the two untyped boolean values.
const (
true = 0 == 0 // Untyped bool.
false = 0 != 0 // Untyped bool.
)
// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8
// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16
// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32
// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64
// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8
// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16
// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32
// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64
// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32
// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64
// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64
// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128
// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string
// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int
// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint
// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8
// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32
主要注意几个点:
type int int
大小至少32位也就是至少4字节,为什么说是至少呢?因为int类型所占字节数跟操作系统有关,如果是32位就是4个字节,如果是64位就是8个字节,type int int
和type int32 int32
不同,int32永远是32位,int64永远是64位。type string string
string可能是空,但不能为nil,这一点和Java不同,Java中String可以为null。string是不可变的,这一点和Java相同。type uintptr uintptr
是一个integer类型,空间足够大可存储任何指针。byte
和uint8
类型是相同的,可以说是uint8
的别称,byte
更简单一些。rune
和int32
类型是相同的,rune
更简单一些。
第二部分
any
// any is an alias for interface and is equivalent to interface in all ways.
type any = interface
any
和interface
是相同的,不要以为是泛型关键词,为了少写一些字母所以会用any
,下面举了一个例子
func convert(t any)
switch t.(type)
case int:
//
case string:
//
case bool:
//
func main()
f(2)
f(true)
f("煎鱼好!")
comparable
// comparable is an interface that is implemented by all comparable types
// (booleans, numbers, strings, pointers, channels, arrays of comparable types,
// structs whose fields are all comparable types).
// The comparable interface may only be used as a type parameter constraint,
// not as the type of a variable.
type comparable interface comparable
comparable
是由所有可比较类型(包括booleans, numbers, strings, pointers, channels,interface, arrays中元素为可比较类型,
以及structs 中所有属性都是可比较类型)实现的接口。只能用于类型参数约束,不用于变量类型比较,举个🌰:
func SumNumbers[K comparable, V int](m map[K]V) V
var s V
for _, v := range m
s += v
return s
//入参
ints := map[string]int
"first": 34,
"second": 12,
//调用
SumIntsOrFloats[string, int](ints)
- T is not an interface type and T supports the operations == and !=; or
- T is an interface type and each type in T’s type set implements comparable.
下面大多数都是上面1类型,其中interface属于上面2类型。支持的类型以下列举出来:
- Boolean values are comparable. Two boolean values are equal if they are either both true or both false.
- Integer values are comparable and ordered, in the usual way.
- Floating-point values are comparable and ordered, as defined by the IEEE-754 standard.
- Complex values are comparable. Two complex values u and v are equal if both real(u) == real(v) and imag(u) == imag(v).
- String values are comparable and ordered, lexically byte-wise.
- Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil. Pointers to distinct zero-size variables may or may not be equal.
- Channel values are comparable. Two channel values are equal if they were created by the same call to make or if both have value nil.
- Interface values are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.for example
interface ~int | ~string
- A value x of non-interface type X and a value t of interface type T are comparable when values of type X are comparable and X implements T. They are equal if t’s dynamic type is identical to X and t’s dynamic value is equal to x.
- Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
- Array values are comparable if values of the array element type are comparable. Two array values are equal if their corresponding elements are equal.
Java中Comparable<T>
接口是用于比较排序的,Golang中comparable是用于类型限定,功能不同,需要注意。
public interface Comparable<T>
public int compareTo(T o);
iota
// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.
iota
在关键字const
出现时重置为0- const中每新增一行常量声明将使iota计数一次,下面举了三个例子
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
const (
n1 = iota //0
n2 //1
_ //有误
n4 //2
)
const (
a,b = iota,iota + 1 //0,1
c,d //1,2
e,f //2,3
)
nil
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type
nil
只能为 pointer, channel, func, interface, map, or slice 类型,不能为基本数据类型
Type
// Type/Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int
type Type1 int
// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int
// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32
// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64
Go 为预定义标识提供的文档说明,在IDE中使用,并非真正实现,不用特别关注。
append
// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
// slice = append(slice, elem1, elem2)
// slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
// slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type
append
函数只能用于slice数据结构上,将元素添加到切片末尾并返回结果- 调用
append
函数只能用原来的切片变量接收返回值 append
追加元素,如果底层数组有空间的话,将新元素放在切片剩余空间中,如果底层数据没有空间,会新创建一个新的底层数组,将原来切片中元素拷贝到新切片中,返回一个新的切片,切片地址信息也会发生改变。append
扩容原理,在一定大小内容量内cap会double增加,在大于阈值后cap按1.25倍增加,目的是节约提前分配空间。
/*例子1*/
var boys []string
//len(boys) = 4, cap(boys) = 4
boys = append(boys, "panda", "jack", "bingo", "hans")
//len(boys) = 5, cap(boys) = 8
boys = append(boys, "baobao")
/*例子2*/
girls := []string"happy","doudou","marni"
girls2 := []string"jiu"
girls = append(girls, girl2...)
/*例子3*/
intSlice := []int1,2,3,4,5,6,7,8,9
//4,5,6,7,8,9
intSlice2 := append(intSlice[:0],intSlice[3:]...)
//1,2,3,7,8,9
intSlice3 := append(intSlice[:3],intSlice[:6]...)
//1,2,3,4,5,6
intSlice4 := append(intSlice[:0],intSlice[:6]...)
/*例子4反面例子*/
slice1 : = []string"hello"
name := "world"
slice2 := []string"goodbye"
//编译错误,必须有接收值
append(slice1, name)
//编译错误,接收slice2不是原slice1
slice2 = append(slice1, name)
copy
// The copy built-in function copies elements from a source slice into a
// destination slice. (As a special case, it also will copy bytes from a
// string to a slice of bytes.) The source and destination may overlap. Copy
// returns the number of elements copied, which will be the minimum of
// len(src) and len(dst).
func copy(dst, src []Type) int
copy
从一个切片拷贝到另一个目的切片上,原切片和目的切片可能交叉,copy
返回复制的元素的个数,为len(src)
和len(dst)
中的最小值- 注意
copy
函数第一个参数是目的切片,第二个参数是原切片
/*例子*/
slice1 := []int1,2,3,4,5
slice2 := []int6,7,8
//slice1 6,7,8,4,5 ,返回3
copy(slice1, slice2)
//slice2 1,2,3 ,返回3
copy(slice2, slice1)
//slice2 2,3,4 ,返回3
copy(slice2, slice1[1:4])
有点类似Java中Arrays.copy()
delete
// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If m is nil or there is no such element, delete
// is a no-op.
func delete(m map[Type]Type1, key Type)
delete
函数用于删除map的key-value,类似于Java Map.remove(Key)操作delete
函数第一个参数为map,第二个参数为key值,注意如果map为空或者map中没有该key,相当于没有做任何操作- 没有返回值,并不知道是否有删除操作或者没有删除操作,需要通过map的大小来判断吗?
len / cap
// The len built-in function returns the length of v, according to its type:
// Array: the number of elements in v.
// Pointer to array: the number of elements in *v (even if v is nil).
// Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
// String: the number of bytes in v.
// Channel: the number of elements queued (unread) in the channel buffer;
// if v is nil, len(v) is zero.
// For some arguments, such as a string literal or a simple array expression, the
// result can be a constant. See the Go language specification's "Length and
// capacity" section for details.
func len(v Type) int
// The cap built-in function returns the capacity of v, according to its type:
// Array: the number of elements in v (same as len(v)).
// Pointer to array: the number of elements in *v (same as len(v)).
// Slice: the maximum length the slice can reach when resliced;
// if v is nil, cap(v) is zero.
// Channel: the channel buffer capacity, in units of elements;
// if v is nil, cap(v) is zero.
// For some arguments, such as a simple array expression, the result can be a
// constant. See the Go language specification's "Length and capacity" section for
// details.
func cap(v Type) int
len
函数可用于array、指向Array的指针、slice、map、string、channelcap
函数可用于array、指向Array的指针、slice、channel,相比len
少了string和map
/*例子1*/
array := [5]int1,2,3
//len(array)为5,cap(array)为5
/*例子2*/
arrayP := &[5]int1,2,3
//len(arrayP)为5,cap(arrayP)为5
/*例子3*/
map1 := map[string]int"panda":4,"marni":3
//len(map1)为2
//slice省略在上面append函数章节有解释
/*例子4*/
str := "hello world"
//len(str)为11
/*例子5*/
intChan = make(chan int, 3)
intChan<-10
intChan<-20
//len(intChan)为2,cap(intChan)为3
make
// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
// Slice: The size specifies the length. The capacity of the slice is
// equal to its length. A second integer argument may be provided to
// specify a different capacity; it must be no smaller than the
// length. For example, make([]int, 0, 10) allocates an underlying array
// of size 10 and returns a slice of length 0 and capacity 10 that is
// backed by this underlying array.
// Map: An empty map is allocated with enough space to hold the
// specified number of elements. The size may be omitted, in which case
// a small starting size is allocated.
// Channel: The channel's buffer is initialized with the specified
// buffer capacity. If zero, or the size is omitted, the channel is
// unbuffered.
func make(t Type, size ...IntegerType) Type
make
函数用于分配内存空间,初始化对象,但是只能用于slice、map、chan类型make
第一个参数是类型,不是值,和new
函数不同的是返回的是这个类型,而不是指向这个类型的指针,下面分别讲解一下三种类型的
/*例子1*/
//len为0,cap为10
slice1 := make([]int, 0, 10)
//len为10,cap为10
slice2 := make([]int,10)
/*例子2*/
//map无需指定容量大小,初始化一个空map
map1 := make(map[string]int)
/*例子3*/
//通道缓存设置为10
channel1 := make(chan int, 10)
//如果为零或忽略大小(不传入第二个参数),则 channel 为无缓冲的
channel2 := make(chan int, 0)
channel3 := make(chan int)
new
// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type
new
函数是分配内存,输入的参数是类型不是值,返回值是这种类型零值的指针,下面举几个🌰
/*例子1*/
num5 := new(int)
fmt.Printf("num5的类型=%T, num5的值=%v, num5的地址=%v\\n", num5, num5, &num5)
//num5的类型=*int, num5的值=0xc00018e0d0, num5的地址=0xc000186008
/*例子2*/
new(pb.ArithService)
//ArithService结构体
type ArithService struct
/*例子3*/
new(Call)
//Call结构体
type Call struct
ServiceMethod string // The name of the service and method to call.
Args any // The argument to the function (*struct).
Reply any // The reply from the function (*struct).
Error error // After completion, the error status.
Done chan *Call // Receives *Call when Go is complete.
complex / real / imag
// The complex built-in function constructs a complex value from two
// floating-point values. The real and imaginary parts must be of the same
// size, either float32 or float64 (or assignable to them), and the return
// value will be the corresponding complex type (complex64 for float32,
// complex128 for float64).
func complex(r, i FloatType) ComplexType
// The real built-in function returns the real part of the complex number c.
// The return value will be floating point type corresponding to the type of c.
func real(c ComplexType) FloatType
// The imag built-in function returns the imaginary part of the complex
// number c. The return value will be floating point type corresponding to
// the type of c.
func imag(c ComplexType) FloatType
复数一般不会用到,不做过多解释。
close
// The close built-in function closes a channel, which must be either
// bidirectional or send-only. It should be executed only by the sender,
// never the receiver, and has the effect of shutting down the channel after
// the last sent value is received. After the last value has been received
// from a closed channel c, any receive from c will succeed without
// blocking, returning the zero value for the channel element. The form
// x, ok := <-c
// will also set ok to false for a closed channel.
func close(c chan<- Type)
close
函数用于chan,chan必须为双向通道或者是单向输入的(send-only)通道,close
作用是不允许再向通道中添加元素,从通道中取出元素时不受影响的。- 当从关闭的通道取出最后一个元素,再从通道取到的将是零值。
x, ok := <-c
对于close来说返回ok为false。
panic
// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated with a non-zero exit code. This
// termination sequence is called panicking and can be controlled by the
// built-in function recover.
func panic(v any)
panic
发生后程序会中断执行,按调用堆栈顺序层层不断向上抛,最后返回一个非0退出码,一般会返回2错误码。panic
是底层抽象的错误,空指针、越界等异常具体异常,一般在业务代码里不要直接使用panic
。- 使用
panic
的场景,举个例子当项目中特别依赖一些组件时,比如一些web项目中经常会在进程启动之前初始化一些mysql,mq句柄。这些实例对业务来说是非常重要的,所以当这些实例初始化失败时我们可以直接让当前程序panic(手动panic),然后及时发现问题并解决。 panic
函数参数可以是任何类型,下面recover
函数是用来处理控制panic
的。
recover
// The recover built-in function allows a program to manage behavior of a
// panicking goroutine. Executing a call to recover inside a deferred
// function (but not any function called by it) stops the panicking sequence
// by restoring normal execution and retrieves the error value passed to the
// call of panic. If recover is called outside the deferred function it will
// not stop a panicking sequence. In this case, or when the goroutine is not
// panicking, or if the argument supplied to panic was nil, recover returns
// nil. Thus the return value from recover reports whether the goroutine is
// panicking.
func recover() any
recover
用于处理控制paniking行为,捕捉panic,恢复程序正常执行,recover
返回值为panic
发生时的记录,包括panic
设置的入参和函数调用的堆栈跟踪信息。- 如果
recover
放在defer
函数以外,recover
返回为nil,将不起控制panic
的作用,下面反例1展示。 - 注意将
defer
语句写在函数的最前面,放在panic
后面将不起作用。
/*正面例子*/
defer func()
err := recover()
if err != nil
fmt.Println("err is", err)
()
panic(errors.New("something wrong"))
/*演示几种recover错误用法*/
//反例1,recover错误用法,此次没有panic发生,recover捕捉不到任何东西,返回nil
fmt.Printf("no panic: %v\\n", recover())
//反例2,引发panic,此时程序终止,不会走到下面p := recover()
panic(errors.New("something wrong"))
//不会走到此unreachale code
p := recover()
fmt.Printf("panic: %s\\n", p)
print / println
// The print built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Print is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func print(args ...Type)
// The println built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Spaces are always added between arguments and a newline is appended.
// Println is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func println(args ...Type)
print()
、println()
标准错误打印print()
、println()
不能打印数组、结构体具体值会打印引用地址值
除非调试启动时和debug时打印日志,其他情况不建议在代码里使用
error
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface
Error() string
- 实现
error
接口的Error()
方法,说明就是一个error类型,如果返回结果为nil说明没有异常。
//自定义异常结构体
type ErrInvalidParam struct
ParamName string
ParamValue string
func (e *ErrInvalidParam) Error() string
return fmt.Sprintf("invalid param: %+v, value: %+v", e.ParamName, e.ParamValue)
//断言机制,对ErrInvalidParam类型处理
e, ok := err.(*ErrInvalidParam)
if ok && e != nil
//...
//类型选择机制,对不同类型异常处理
if err != nil
switch err.(type)
case *ErrInvalidParam:
//..
return
default:
//...
return
以上是关于源码阅读苦练基本功Golang内置函数分析的主要内容,如果未能解决你的问题,请参考以下文章