go version 1.13
基礎(chǔ)語法
1. new(T)
和 make(T,args)
的區(qū)別遍坟?
new(T) 返回對(duì)應(yīng)T的指針類型晴股,即*T,指針指向的數(shù)據(jù)其值為零值电湘,make(T,args) 只能初始化 slice寂呛,map刽虹,chan這三種類型呢诬,T的初始化值也為零值胖缤,但是返回類型是T類型的引用哪廓,而不是指針類型。
2. slice 使用append()函數(shù)時(shí)分俯,參數(shù)為slice和相同類型的元素時(shí)哆料,有啥不同东亦?
slice追加slice時(shí),需要在被追加的slice后面加...
奋渔,追加元素時(shí)而不需要壮啊,具體可看下面代碼片斷。
s1 := []int{1, 2, 3}
s2 := []int{4, 5}
s1 = append(s1, s2...)
fmt.Println(s1)
s1 = append(s1, 6, 7)
fmt.Println(s1)
3. 變量的聲明方式有哪幾種玄渗?
有四種。
方式一:var 變量名 變量類型辈灼,這種方式變量值為零值巡莹,如下所示:
var s string
var i int
var m map[string]string
fmt.Printf("s:%T,%q,i:%T,%v,m:%T,%v",s,s,i,i,m,m)
代碼輸出結(jié)果:s:string,"",i:int,0,m:map[string]string,map[]
方式二: var 變量名 變量類型 = 表達(dá)式甜紫,表達(dá)式指定變量的初始值,如下所示:
var s1 string = "Hello,王二狗"
var i1 int = 520
var s2 []string = []string{"學(xué)習(xí)","go"}
fmt.Printf("s1:%T,%q,i1:%T,%v,s2:%T,%v\n",s1,s1,i1,i1,s2,s2)
代碼輸出結(jié)果:s1:string,"Hello,王二狗",i1:int,520,s2:[]string,[學(xué)習(xí) go]
方式三(同時(shí)聲明多個(gè)變量):var 變量名1,變量名2 = 值1,值2腰根,如下所示:
var s3,i2 = "Happy",521
fmt.Printf("s3:%T,%q,i2:%T,%d\n",s3,s3,i2,i2)
代碼輸出結(jié)果:s3:string,"Happy",i2:int,521
方式四:變量名 := 值,注意额嘿,這種短變量聲明方式只能使用在函數(shù)內(nèi)部劣挫,如下所示:
s4 := "技術(shù)人的自我修養(yǎng)"
i3 := 12345
fmt.Printf("s4:%T,%q,i3:%T,%d\n",s4,s4,i3,i3)
代碼輸出結(jié)果:s4:string,"技術(shù)人的自我修養(yǎng)",i3:int,12345
4. 常量如何聲明压固?
常量的聲明要使用關(guān)鍵字const
,常量在聲明的時(shí)候必須賦值坎炼,方式有兩種拦键。
方式一:const 常量名 = 常量值矿咕。
const s1 = "Happy"
const i = 1234
方式二:參考代碼片斷。
const(
s2 = "編程學(xué)習(xí)"
i2 = 2020
)
5. Go語言中捡絮,哪些變量類型可以直接比較莲镣,哪些滿足前提條件下可比較瑞侮,哪些不能比較鼓拧?
布爾類型(boolean)越妈、整型(integer)梅掠、浮點(diǎn)數(shù)(float)、復(fù)數(shù)(complex)酪我、字符串(string)且叁、指針類型(pointer)逞带、通道(channel)、接口類型(interface)可以直接進(jìn)行比較汇陆。
結(jié)構(gòu)體(struct)带饱、數(shù)組(array)阅羹,如果元素都是能直接比較類型捏鱼,(即元素類型屬于前一類能直接比較的),則對(duì)應(yīng)的結(jié)構(gòu)體和數(shù)據(jù)也可比較轨淌。
切片(slice)看尼、map和函數(shù)類型(func)不能進(jìn)行比較藏斩,除非是與nil
進(jìn)行比較。
注意:接口類型雖可直接比較媳拴,但如果實(shí)現(xiàn)接口的對(duì)應(yīng)類型不能直接進(jìn)行比較的話屈溉,也會(huì)引發(fā)panic
導(dǎo)致程序異常退出,如下代碼所示:
// T 定義的一個(gè)演示接口
type T interface {
hello()
}
// PersonA 演示用結(jié)構(gòu)體
type PersonA struct {
m map[string]int
}
// PersonB 演示用結(jié)構(gòu)體
type PersonB struct {
}
func (p *PersonA) hello() {
fmt.Println("hello PersonA")
}
func (p *PersonB) hello() {
fmt.Println("hello PersonB")
}
func main() {
var p1 PersonA
var p2 PersonB
fmt.Println(p1 == p2)
}
運(yùn)行以上代碼會(huì)提示:invalid operation: p1 == p2 (mismatched types PersonA and PersonB)
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.
A comparison of two interface values with identical dynamic types causes a run-time panic if values of that type are not comparable. This behavior applies not only to direct interface value comparisons but also when comparing arrays of interface values or structs with interface-valued fields.
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.
Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil.
Comparison of pointer, channel, and interface values to nil is also allowed and follows from the general rules above.
以上英文片斷出自:https://golang.org/ref/spec#Comparison_operators帆赢。
6.通過指針變量p訪問成員變量的方式?
// p.name , (*p).name 或 *&p.name
type person struct {
name string
}
func main() {
p1 := person{name: "王二狗"}
p := &p1
fmt.Printf("%s,%s,%s\n", p.name, (*p).name, *&p.name)
}
7.類型別名與自定義的區(qū)別
Go中可用type
關(guān)鍵字自定義類型砰左,類型別名相當(dāng)于給類型T
取一個(gè)別名匿醒,別名指向的類型本質(zhì)上還是屬于T
,二者的語法區(qū)別如下所示:
// MyInt 自定義類型:MyInt,屬于一個(gè)新類型缠导,它具有int的特性
type MyInt int
// MyInt2 類型別名:給int類型取一個(gè)別名
type MyInt2 = int
func main() {
var i int = 1234
// 編譯不通過廉羔,因?yàn)镚o是強(qiáng)類型語言,不能直接把int類型的變量賦給MyInt類型僻造,可通過強(qiáng)轉(zhuǎn)賦值
//var i1 MyInt = i
var i1 MyInt = MyInt(i)
var i2 MyInt2 = i
fmt.Printf("i1 type:%T,i1=%d,i2 type:%T,i2=%d\n", i1, i1, i2, i2)
}
// 輸出結(jié)果:i1 type:main.MyInt,i1=1234,i2 type:int,i2=1234
8.nil
可以給哪些類型的變量賦值憋他?
nil 只能給 chan
,slice
,map
,interface
,func
和指針類型賦值髓削。注意:error
本質(zhì)上屬于interface
類型,參考源代碼定義立膛,如下:
type error interface {
Error() string
}
9.說說Go中的init()函數(shù)揪罕?
init()
是包的初始化函數(shù),用于程序在執(zhí)行對(duì)應(yīng)包的代碼前做一些初始化工作宝泵;每個(gè)包可以有多個(gè)
init()
函數(shù)好啰;每個(gè)包的同一個(gè)源碼文件也可以有多個(gè)
init()
函數(shù);同一個(gè)源碼文件的
init()
函數(shù)執(zhí)行順序沒有明確定義儿奶;init()
函數(shù)不能手工調(diào)用框往,只能在引入包時(shí)自動(dòng)執(zhí)行;-
不同包的
init()
函數(shù)調(diào)用關(guān)系可參考下圖:
10.一個(gè)接口如果被*T
類型的變量實(shí)現(xiàn)闯捎,T
可以賦值給該接口類型嗎椰弊?
不能,參考以下代碼:
// Walker 接口
type Walker interface {
Walk() string
}
// Dog 狗
type Dog struct{}
// Walk 小狗跑
func (d *Dog) Walk() string {
return "小狗奔跑"
}
func main() {
var walker Walker
wangcai := &Dog{}
fugui := Dog{}
walker = wangcai
fmt.Println("旺柴", wangcai.Walk())
fmt.Println("接口", walker.Walk())
// walker = fugui 編譯不通過瓤鼻,因?yàn)閷?shí)現(xiàn)Walker的是 *Dog類型
walker = &fugui
// Dog 和 *Dog 都可以調(diào)用 Walk()函數(shù)
fmt.Println("富貴", fugui.Walk())
fmt.Println("接口", walker.Walk())
}