射人先射马,擒贼先擒王
冷兵器时代的战争相比于现代战争,无论是武器装备的精良程度,还是士兵的个人素质,都有着天壤之别,但有一点无论是现代战争还是古代战争,都遵循着一条金科玉律不曾改变:射人先射马,擒贼先擒王。只有将敌人的中枢神经指挥系统破毁掉,才能实现快速取得胜利的目标,以最小的代价不战而屈人之兵,同样的道理,日常的工作虽然在大部分的时间是建立在框架的开发运用基础上,但是官方原生提供的API还是需要熟练掌握的,手中无剑而心中有剑是区分一个高手和平庸武师的分水岭;手中无码,心中有码是判断一个工程师的优劣标准。
go语言的builtin包
go语言的builtin包为go语言提供了一些内置的类型和函数,下面主要针对一些重要的内置类型展开讲解。
1、实战案例演练
package main
/*********************************************************************/
/**************** golang中builtin包相关API讲解 **********************/
/********************************************************************/
/*
Constants
Variables
func append(slice []Type, elems ...Type) []Type
func cap(v Type) int
func close(c chan<- Type)
func complex(r, i FloatType) ComplexType
func copy(dst, src []Type) int
func delete(m map[Type]Type1, key Type)
func imag(c ComplexType) FloatType
func len(v Type) int
func make(t Type, size ...IntegerType) Type
func new(Type) *Type
func panic(v interface{})
func print(args ...Type)
func println(args ...Type)
func real(c ComplexType) FloatType
func recover() interface{}
type ComplexType
type FloatType
type IntegerType
type Type
type Type1
type bool
type byte
type complex128
type complex64
type error
type float32
type float64
type int
type int16
type int32
type int64
type int8
type rune
type string
type uint
type uint16
type uint32
type uint64
type uint8
type uintptr
*/
func main() {
/**
*内建函数append将元素追加到切片的末尾。若它有足够的容量,其目标就会重新切片以容纳新的元素。
*否则,就会分配一个新的基本数组。append返回更新后的切片,因此必须存储追加后的结果。
*func append(slice []Type, elems ...Type) []Type
*/
//内置函数append()有三种使用的方法,第一种常规的使用方法,第一个参数为切片,第二个参数为可变参数
//第二种使用的方法是,第一个参数为切片,第二个参数也为切片,结果追加到第一个参数的末尾
//第三种使用的方法是,第一个参数为字节切片,第二个参数为字符串(被当做字节数组传入【末尾的三个点不能省略】)
/*
slice := append([]int{1, 2, 3}, 4, 5, 6)
fmt.Println(slice)
slice2 := append([]int{1, 2, 3}, []int{4, 5, 6}...)
fmt.Println(slice2)
slice3 := append([]byte("hello"), "world"...)
fmt.Println(slice3)
*/
/**
*内建函数cap返回v的容量,这取决于具体类型.
*数组:v中元素的数量,与 len(v)相同;
*数组指针:*v中元素的数量,与len(v)相同;
*切片:切片的容量(底层数组的长度;若v为nil,cap(v) 即为零
*信道:按照元素的单元,相应信道缓存的容量;若v为nil,cap(v)即为零
*func cap(v Type) int
*/
/*
arr := [...]int{1, 2, 3, 4}
fmt.Println(cap(arr))
var arr2 * [4]int
var arr3 = [4]int{1,2,3,4}
arr2 = &arr3
fmt.Println(cap(arr2))
slice := []int{1, 2, 3}
fmt.Println(cap(slice))
slice2 := make([]int, 10)
fmt.Println(cap(slice2))
var ch chan int
fmt.Println(cap(ch))
ch2 := make(chan int, 10)
fmt.Println(cap(ch2))
*/
/**
*close函数是一个内建函数, 用来关闭channel,这个channel要么是双向的, 要么是只写的(chan<- Type)。
*这个方法应该只由发送者调用, 而不是接收者。当最后一个发送的值都被接收者从关闭的channel(下简称为c)中接收时,
*接下来所有接收的值都会非阻塞直接成功,返回channel元素的零值。
*func close(c chan<- Type)
*/
/*
ch := make(chan int, 5)
for i := 0; i < 5; i++ {
ch <- i
}
close(ch)
for i := 0; i < 10; i++ {
e, ok := <- ch
fmt.Printf("%v, %v\n", e, ok)
if !ok {
break
}
}
×/
/**
*使用实部r和虚部i生成一个复数
*func complex(r, i FloatType) ComplexType
*/
/*
var x complex64 = complex(1, 2)
var y complex64 = complex(1, 2)
fmt.Println(x * y)
fmt.Println(imag(x*y))
fmt.Println(real(x*y))
*/
/**
*内建函数copy将元素从来源切片复制到目标切片中,也能将字节从字符串复制到字节切片中。
*copy返回被复制的元素数量,它会是 len(src) 和 len(dst) 中较小的那个。来源和目标的底层内存可以重叠。
*func copy(dst, src []Type) int
*/
/*
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice1, slice2)
fmt.Println(slice1, slice2)
slice3 := []int{5, 4, 3}
slice4 := []int{1, 2, 3, 4, 5}
copy(slice3, slice4)
*/
/**
*内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作。
*func delete(m map[Type]Type1, key Type)
*/
/*
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
fmt.Println("Deleting values")
name, ok := m["a"]
fmt.Println(name,ok)
delete(m,"a")
name,ok = m["a"]
fmt.Println(name,ok)
*/
/**
*返回复数c的虚部。
*func imag(c ComplexType) FloatType
*/
/*
var x complex64 = complex(1, 2)
fmt.Println(imag(x))
*/
/**
*内建函数len返回v的长度,这取决于具体类型:
*数组:v中元素的数量
*数组指针:*v中元素的数量(v为nil时panic)
*切片、映射:v中元素的数量;若v为nil,len(v)即为零
*字符串:v中字节的数量
*通道:通道缓存中队列(未读取)元素的数量;若v为 nil,len(v)即为零
*func len(v Type) int
*/
/*
arr := [...]int{1, 2, 3, 4}
fmt.Println(len(arr))
var arr2 *[4]int
var arr3 = [4]int{1, 2, 3, 4}
arr2 = &arr3
fmt.Println(len(arr2))
slice := []int{}
fmt.Println(len(slice))
slice2 := []int{1, 2, 3}
fmt.Println(len(slice2))
var ch chan int
fmt.Println(len(ch))
ch2 := make(chan int, 10)
ch2 <- 1
ch2 <- 2
fmt.Println(len(ch2))
str := "sdgfvfg"
fmt.Println(len(str))
*/
/**
*内建函数make分配并初始化一个类型为切片、映射、或通道的对象。其第一个实参为类型,
*而非值。make的返回类型与其参数相同,而非指向它的指针。其具体结果取决于具体的类型:
*切片:size指定了其长度。该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;
*它必须不小于其长度,因此 make([]int, 0, 10) 会分配一个长度为0,容量为10的切片。
*映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个
*小的起始大小。
*通道:通道的缓存根据指定的缓存容量初始化。若 size为零或被省略,该信道即为无缓存的。
*func make(t Type, size ...IntegerType) Type
*/
/*
slice := make([]int, 10)
fmt.Println(slice)
m := make(map[string]int, 10)
fmt.Println(m)
ch := make(chan int, 10)
fmt.Println(ch)
*/
/**
*内建函数new分配内存。其第一个实参为类型,而非值。其返回值为指向该类型的新分配的零值的指针。
*func new(Type) *Type
*/
/*
var i *int
i=new(int)
*i=10
fmt.Println(*i)
*/
/**
*内建函数panic停止当前Go程的正常执行
*func panic(v interface{})
*/
/*
panic("fault")
fmt.Println("panic")
*/
/**
*
*func println(args ...Type)
*/
/*
fmt.Println("1", "2", "3")
*/
/**
*返回复数c的实部。
*func real(c ComplexType) FloatType
*/
/*
var x complex64 = complex(1, 2)
fmt.Println(real(x))
*/
/**
*内建函数recover允许程序管理恐慌过程中的Go程。在defer的函数中,
*执行recover调用会取回传至panic调用的错误值,恢复正常执行,停止恐慌过程。
*若recover在defer的函数之外被调用,它将不会停止恐慌过程序列。在此情况下,
*或当该Go程不在恐慌过程中时,或提供给panic的实参为nil时,recover就会返回nil。
*func recover() interface{}
*/
/*
defer func() {
fmt.Println("1")
}()
defer func() {
if err := recover(); err!= nil {
fmt.Println(err)
}
}()
panic("fault")
fmt.Println("2")
*/
}
小结
built包部分的内容可能是相对简单的,同时内容可能也是最少的,但从另一个角度上来讲这部分的api的内容也是必须掌握的,其实好多的程序员之所以写不出优秀的代码,很大一部分的原因就是对基础的api不熟悉导致的,明明语言本身已经有了现存的解决方案,但是因为不熟悉api的原因还是得自己去从零去实现,不是说自己去实现不好,但是整体而言肯定不如官方的实现方案好。