從如下幾個方面介紹GO語言的數(shù)據(jù)

1. 字符串 2. 數(shù)組 3. 切片 4. 字典 5. 結(jié)構(gòu)
Go語言中的字符串是由一組不可變的字節(jié)(byte)序列組成從源碼文件中看出其本身是一個復(fù)合結(jié)構(gòu)
string.go
type stringStruct struct {
str unsafe.Pointer
len int
}字符串中的每個字節(jié)都是以UTF-8編碼存儲的Unicode字符字符串的頭部指針指向字節(jié)數(shù)組的開始但是沒有NULL或'\0'結(jié)尾標志。 表示方式很簡單用雙引號("")或者反引號(``)它們的區(qū)別是
雙引號之間的轉(zhuǎn)義符會被轉(zhuǎn)義而反引號之間的轉(zhuǎn)義符保持不變
反引號支持跨行編寫而雙引號則不可以
{
println("hello\tgo") //輸出hello go
println(`hello\tgo`) //輸出hello\tgo
}
{
println( "hello
go" )//syntax error: unexpected semicolon or newline, expecting comma or )
println(`hello
go`) //可以編譯通過
}
輸出
hello
go在前面類型的章節(jié)中描述過字符串的默認值是""而不是nil,比如
var s string println( s == "" ) //true println( s == nil ) //invalid operation: s == nil (mismatched types string and nil)
Go字符串支持 "+ , += , == , != , < , >" 六種運算符
Go字符串允許用索引號訪問字節(jié)數(shù)組(非字符)但不能獲取元素的地址比如
{
var a = "hello"
println(a[0]) //輸出 104
println(&a[1]) //cannot take the address of a[1]
}Go字符串允許用切片的語法返回子串(起始和結(jié)束索引號)比如
var a = "0123456" println(a[:3]) //0,1,2 println(a[1:3]) //1,2 println(a[3:]) //3,4,5,6
日常開發(fā)中經(jīng)常會有遍歷字符串的場景比如
{
var a = "Go語言"
for i:=0;i < len(a);i++{ //以byte方式按字節(jié)遍歷
fmt.Printf("%d: [%c]\n", i, a[i])
}
for i, v := range a{ //以rune方式遍歷
fmt.Printf("%d: [%c]\n", i, v)
}
}
輸出
0: [G]
1: [o]
2: [è]
3: [ˉ]
4: [-]
5: [è]
6: [¨]
7: []
0: [G]
1: [o]
2: [語]
5: [言]在Go語言中字符串的底層使用的是不可以改變的byte數(shù)組存的所以在用byte輪詢方式時每次得到的只有一個byte而中文字符則是占3個byte的。rune采用計算字符串長度的方式與byte方式不同比如
println(utf8.RuneCountInString(a)) // 結(jié)果為 4 println(len(a)) // 結(jié)果為 8
所以如果想要獲得期待的那種結(jié)果的話需要先將字符串a(chǎn)轉(zhuǎn)換為rune切片再使用內(nèi)置的len函數(shù)比如:
{
r := []rune(a)
for i:= 0;i < len(r);i++{
fmt.Printf("%d: [%c]\n", i, r[i])
}
}所以在遍歷或處理的字符串的情況下如果其中存在中文盡量使用rune方式處理。
轉(zhuǎn)換
前面講過不能修改原字符串如果修改的話需要將字符串轉(zhuǎn)換成[]byte或[]rune , 然后在轉(zhuǎn)換回來比如
{
var a = "hello go"
a[1] = 'd' //cannot assign to a[1]
}
{
var a = "hello go"
bs := []byte(a)
...
s2 := string(bs)
rs := []rune(a)
...
s3 := string(rs)
}Go語言支持用"+"運算符進行字符串拼接但是每次拼接都需要重新分配內(nèi)存如果頻繁構(gòu)造一個很長的字符串則性能影響就會很大比如
func test1()string{
var s string
for i:= 0;i < 1000 ;i++{
s += "a"
}
return s
}
func Benchmark_test1(b *testing.B){
for i:= 0;i < b.N; i++{
test1()
}
}
輸出
# go test str1_b_test.go -bench="test1" -benchmem
Benchmark_test1-2 5000 227539 ns/op 530338 B/op 999 allocs/op常用的改進方法是預(yù)分配足夠的內(nèi)存空間然后使用strings.Join函數(shù)該函數(shù)會統(tǒng)計出所有參數(shù)的長度并一次性完成內(nèi)存分配操作改進一下上面的代碼
func test()string{
s := make([]string,1000)
for i:= 0;i < 1000 ;i++{
s[i] = "a"
}
return strings.Join(s,"")
}
func Benchmark_test(b *testing.B){
for i:= 0;i < b.N; i++{
test()
}
}
輸出
# go test -v b_test.go -bench="test1" -benchmem
Benchmark_test1-2 200000 10765 ns/op 2048 B/op 2 allocs/op在日常開發(fā)中可以使用fmt.Sprintf函數(shù)來格式化和拼接較少的字符串操作比如
{
a := 10010
as := fmt.Sprintf("%d",a)
fmt.Printf("%T , %v\n",as,as)
}數(shù)組
數(shù)組是內(nèi)置(build-in)類型是一組存放相同類型數(shù)據(jù)的集合數(shù)組的數(shù)據(jù)類型是由存儲的元素類型和數(shù)組的長度共同決定的,即使元素類型相同但是長度不同數(shù)組也不屬于同一類型。數(shù)組初始化之后長度是固定無法修改的數(shù)組也支持邏輯判斷運算符 "==","="定義方式如下
{
var a [10]int
var b [20]int
println(a == b) //invalid operation: a == b (mismatched types [10]int and [20]int)
}數(shù)組的初始化相對靈活下標索引值從0開始支持按索引位置初始化對于未初始化的數(shù)組編譯器將給以默認值。
{
var a[4] int //元素初始化為0
b := [4] int{0,1} //未初始化的元素將被初始化為0
c := [4] int{0, 2: 3} //可指定索引位置初始化
d := [...]int{0,1,2} //編譯器根據(jù)初始化值數(shù)量來確定數(shù)組的長度
e := [...]int{1, 3:3} //支持索引位置初始化但數(shù)組長度與其無關(guān)
type user struct{
name string
age int
}
d := [...] user{ //復(fù)合數(shù)據(jù)類型數(shù)組可省略元素初始化類型標簽
{"a",1},
{"b",2},
}
}定義多維數(shù)組時只有數(shù)組的第一維度允許使用 "..."
{
x := [2]int{2,2}
a := [2][2]int{{1,2},{2,2}}
b := [...][2]int{{2,3},{2,2},{3,3}}
c := [...][2][2]int{{ {2,3},{2,2} },{{3,3},{4,4}} }
}計算數(shù)組長度時無論使用內(nèi)置的len還是cap返回的都是第一維度的長度比如
{
fmt.Println(x, len(x), cap(x))
fmt.Println(a, len(a), cap(x))
fmt.Println(b, len(b), cap(x))
fmt.Println(c, len(c), cap(x))
}
輸出
[2 2] 2 2
[[1 2] [2 2]] 2 2
[[2 3] [2 2] [3 3]] 3 2
[[[2 3] [2 2]] [[3 3] [4 4]]] 2 2數(shù)組指針&指針數(shù)組
數(shù)組除了可以存放具體類型的數(shù)據(jù)也可以存放指針比如
{
x, y := 10, 20
a := [...]*int{&x, &y} //指針數(shù)組
p := &a //數(shù)組的指針
}數(shù)組復(fù)制
Go語言數(shù)組是值(非引用)類型所以在賦值和參數(shù)傳遞過程中都會復(fù)制整個數(shù)組數(shù)據(jù)比如:
func test(x [2]int){
fmt.Printf("x:= %p,%v\n", &x, x)
}
func main(){
a := [2] int{1, 2}
test(a) //傳參過程中完全復(fù)制
var b [2]int
b = a //賦值過程中完全復(fù)制
fmt.Printf("a:= %p,%v\n", &a, a)
fmt.Printf("b:= %p,%v\n", &b, b)
}
輸出
x:= 0xc42000a330,[1 2]
a:= 0xc42000a320,[1 2]
b:= 0xc42000a370,[1 2]借鑒: 雨痕<GO學(xué)習(xí)筆記>
討論學(xué)習(xí): 675020908
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準確進行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。
本文題目:golang數(shù)據(jù)一(字符串、數(shù)組和數(shù)組指針)-創(chuàng)新互聯(lián)
本文來源:http://chinadenli.net/article12/hpidc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、服務(wù)器托管、微信小程序、移動網(wǎng)站建設(shè)、微信公眾號、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)