package main // package關鍵字聲明包名
// 導入語句
import "fmt"
/*
函數外只能放置標識符(變量、常量、函數、類型)的聲明
不能放置fmt.Println("Hello World")這樣的語句
*/
// 程序的入口函數,如果你要編譯一個可執行的文件,必須要聲明一個main包,而且一定要有一個main函數
func main() {
fmt.Println("Hello World")
}
變量和常量標識符和關鍵字標識符
在程式語言中標識符就是程式設計師定義的具有特殊意義的詞,比如變量名、常量名、函數名等等。Go語言中標識符由字母數字和_(下劃線)組成,並且只能以字母和_開頭。舉幾個例子:abc, _, _123, a123。
關鍵字
關鍵字是指程式語言中預先定義好的具有特殊含義的標識符。關鍵字和保留字都不建議用作變量名。
Go語言中有25個關鍵字:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var此外,Go語言中還有37個保留字:
Constants: true false iota nil
Types: int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error
Functions: make len cap new append copy close delete
complex real imag
panic recover
變量變量的來歷
程序運行過程中的數據都是保存在內存中,我們想要在代碼中操作某個數據時就需要去內存上找到這個變量,但是如果我們直接在代碼中通過內存地址去操作變量的話,代碼的可讀性會非常差而且還容易出錯,所以我們就利用變量將這個數據的內存地址保存起來,以後直接通過這個變量就能找到內存上對應的數據了。
變量類型
變量(Variable)的功能是存儲數據。不同的變量保存的數據類型可能會不一樣。經過半個多世紀的發展,程式語言已經基本形成了一套固定的類型,常見變量的數據類型有:整型、浮點型、布爾型等。
Go語言中的每一個變量都有自己的類型,並且變量必須經過聲明才能開始使用。
變量聲明
Go語言中的變量需要聲明後才能使用,同一作用域內不支持重複聲明。並且Go語言的變量聲明後必須使用。
標準聲明:
Go語言的變量聲明格式為:
var 變量名 變量類型變量聲明以關鍵字var開頭,變量類型放在變量的後面,行尾無需分號。舉個例子:
var name string
var age int
var isOk bool
批量聲明
每聲明一個變量就需要寫var關鍵字會比較繁瑣,go語言中還支持批量變量聲明:
var (
a string
b int
c bool
d float32
)
變量的初始化
Go語言在聲明變量的時候,會自動對變量對應的內存區域進行初始化操作。每個變量會被初始化成其類型的默認值,例如:整型和浮點型變量的默認值為0。字符串變量的默認值為空字符串。布爾型變量默認為false。切片、函數、指針變量的默認為nil。
當然我們也可在聲明變量的時候為其指定初始值。變量初始化的標準格式如下:
var 變量名 類型 = 表達式舉個例子:
var name string = "Jerry"
var age int = 18或者一次初始化多個變量
var name, age = "Jerry", 20
類型推導
有時候我們會將變量的類型省略,這個時候編譯器會根據等號右邊的值來推導變量的類型完成初始化。
var name = "Jerry"
var age = 18
短變量聲明
在函數內部,可以使用更簡略的 := 方式聲明並初始化變量。
package main
import (
"fmt"
)
// 全局變量m
var m = 100
func main() {
n := 10
m := 200 // 此處聲明局部變量m
fmt.Println(m, n)
}
匿名變量
在使用多重賦值時,如果想要忽略某個值,可以使用匿名變量(anonymous variable)。匿名變量用一個下劃線_表示,例如:
func foo() (int, string) {
return 10, "Q1mi"
}
func main() {
x, _ := foo()
_, y := foo()
fmt.Println("x=", x)
fmt.Println("y=", y)
}匿名變量不佔用命名空間,不會分配內存,所以匿名變量之間不存在重複聲明。(在Lua等程式語言裡,匿名變量也被叫做啞元變量。)
注意事項:
函數外的每個語句都必須以關鍵字開始(var、const、func等)
:=不能使用在函數外。
_多用於佔位,表示忽略值。
常量相對於變量,常量是恆定不變的值,多用於定義程序運行期間不會改變的那些值。常量的聲明和變量聲明非常類似,只是把var換成了const,常量在定義的時候必須賦值。
const pi = 3.1415
const e = 2.7182聲明了pi和e這兩個常量之後,在整個程序運行期間它們的值都不能再發生變化了。
多個常量也可以一起聲明:
const (
pi = 3.1415
e = 2.7182
)const同時聲明多個常量時,如果省略了值則表示和上面一行的值相同。例如:
const (
n1 = 100
n2
n3
)上面示例中,常量n1、n2、n3的值都是100。
iota
iota是go語言的常量計數器,只能在常量的表達式中使用。
iota在const關鍵字出現時將被重置為0。const中每新增一行常量聲明將使iota計數一次(iota可理解為const語句塊中的行索引)。使用iota能簡化定義,在定義枚舉時很有用。
舉個例子:
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
幾個常見的ioda示例
使用_跳過某些值:
const (
n1 = iota //0
n2 //1
_
n4 //3
)iota聲明中間插隊:
const (
n1 = iota //0
n2 = 100 //100
n3 = iota //2
n4 //3
)
const n5 = iota //0定義數量級 (這裡的<<表示左移操作,1<<10表示將1的二進位表示向左移10位,也就是由1變成了10000000000,也就是十進位的1024。同理2<<2表示將2的二進位表示向左移2位,也就是由10變成了1000,也就是十進位的8。)
const (
_ = iota
KB = 1 << (10 * iota)
MB = 1 << (10 * iota)
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)多個iota定義在一行:
const (
a, b = iota + 1, iota + 2 //1,2
c, d //2,3
e, f //3,4
)
Go語言基礎之基本數據類型Go語言中有豐富的數據類型,除了基本的整型、浮點型、布爾型、字符串外,還有數組、切片、結構體、函數、map、通道(channel)等。Go 語言的基本類型和其他語言大同小異。
基本數據類型整型分為以下兩個大類:按長度分為:int8、int16、int32、int64 對應的無符號整型:uint8、uint16、uint32、uint64
其中,uint8就是我們熟知的byte型,int16對應C語言中的short型,int64對應C語言中的long型。
類型描述uint8無符號 8位整型 (0 到 255)uint16無符號 16位整型 (0 到 65535)uint32無符號 32位整型 (0 到 4294967295)uint64無符號 64位整型 (0 到 18446744073709551615)int8有符號 8位整型 (-128 到 127)int16有符號 16位整型 (-32768 到 32767)int32有符號 32位整型 (-2147483648 到 2147483647)int64有符號 64位整型 (-9223372036854775808 到 9223372036854775807)
特殊整型
類型描述uint32位作業系統上就是uint32,64位作業系統上就是uint64int32位作業系統上就是int32,64位作業系統上就是int64uintptr無符號整型,用於存放一個指針注意: 在使用int和 uint類型時,不能假定它是32位或64位的整型,而是考慮int和uint可能在不同平臺上的差異。
注意事項: 獲取對象的長度的內建len()函數返回的長度可以根據不同平臺的字節長度進行變化。實際使用中,切片或 map 的元素數量等都可以用int來表示。在涉及到二進位傳輸、讀寫文件的結構描述時,為了保持文件的結構不會受到不同編譯目標平臺字節長度的影響,不要使用int和 uint。
package main
import "fmt"
func main() {
// 查看變量類型
i1 := 30
fmt.Printf("%T \n", i1) // int
// 聲明int8類型變量
i2 := int8(36) // 明確指定int8類型,否則就是默認為int類型
fmt.Printf("%T \n", i2) // int8
}
八進位&十六進位
Go語言中無法直接定義二進位數,關於八進位和十六進位數的示例如下:
package main
import "fmt"
func main() {
// 十進位
var a = 101 // 類型推導
fmt.Printf("%d \n", a) // 101
fmt.Printf("%b \n", a) // 1100101 佔位符%b表示二進位
fmt.Printf("%o \n", a) // 145 十進位轉成八進位
fmt.Printf("%x \n", a) // 65
// 八進位 以0開頭
b := 077 // 短變量聲明
fmt.Printf("%d \n", b) // 63 八進位轉成十進位
// 十六進位 以0x開頭
var c int = 0x1234567
fmt.Printf("%d \n", c) // 19088743 十六進位轉成十進位
}
浮點型
Go語言支持兩種浮點型數:float32和float64。這兩種浮點型數據格式遵循IEEE 754標準:float32 的浮點數的最大範圍約為 3.4e38,可以使用常量定義:math.MaxFloat32。float64 的浮點數的最大範圍約為 1.8e308,可以使用一個常量定義:math.MaxFloat64。
列印浮點數時,可以使用fmt包配合動詞%f,代碼如下:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Printf("%f\n", math.Pi)
fmt.Printf("%.2f\n", math.Pi)
}
複數
complex64和complex128
var c1 complex64
c1 = 1 + 2i
var c2 complex128
c2 = 2 + 3i
fmt.Println(c1)
fmt.Println(c2)複數有實部和虛部,complex64的實部和虛部為32位,complex128的實部和虛部為64位(咱們就放過自己,別去管這玩意了,這東西基本沒咋用到!)。
布爾值
Go語言中以bool類型進行聲明布爾型數據,布爾型數據只有true和false兩個值。
注意:
布爾類型變量的默認值為false。
Go 語言中不允許將整型強制轉換為布爾型.
布爾型無法參與數值運算,也無法與其他類型進行轉換。
字符串
Go語言中的字符串以原生數據類型出現,使用字符串就像使用其他原生數據類型(int、bool、float32、float64 等)一樣。Go 語言裡的字符串的內部實現使用UTF-8編碼。字符串的值為"中的內容,可以在Go語言的源碼中直接添加非ASCII碼字符,例如:
s1 := "hello" // 字符串
s2 := "你好" // 字符串
字符串轉義符
Go 語言的字符串常見轉義符包含回車、換行、單雙引號、制表符等,如下表所示:
轉義符含義\r回車符(返回行首)\n換行符(直接跳到下一行的同列位置)\t制表符\'單引號\"雙引號\\反斜槓舉個例子,我們要列印一個Windows平臺下的一個文件路徑:
package main
import (
"fmt"
)
func main() {
fmt.Println("str := \"c:\\Code\\lesson1\\go.exe\"")
}
多行字符串
Go語言中要定義一個多行字符串時,就必須使用反引號字符:
s1 := `第一行
第二行
第三行
`
fmt.Println(s1)反引號間換行將被作為字符串中的換行,但是所有的轉義字符均無效,文本將會原樣輸出。
字符串的常用操作
方法介紹len(str)求長度+或fmt.Sprintf拼接字符串strings.Split分割strings.contains判斷是否包含strings.HasPrefix,strings.HasSuffix前綴/後綴判斷strings.Index(),strings.LastIndex()子串出現的位置strings.Join(a[]string, sep string)join操作
byte和rune類型
組成每個字符串的元素叫做「字符」,可以通過遍歷或者單個獲取字符串元素獲得字符。字符用單引號(』)包裹起來,如:
var a := '中'
var b := 'x'Go 語言的字符有以下兩種:
uint8類型,或者叫 byte 型,代表了ASCII碼的一個字符。
rune類型,代表一個 UTF-8字符。
當需要處理中文、日文或者其他複合字符時,則需要用到rune類型。rune類型實際是一個int32。
Go 使用了特殊的 rune 類型來處理 Unicode,讓基於 Unicode 的文本處理更為方便,也可以使用 byte 型進行默認字符串處理,性能和擴展性都有照顧。
// 遍歷字符串
func traversalString() {
s := "hello你好"
for i := 0; i < len(s); i++ { //byte
fmt.Printf("%v(%c) ", s[i], s[i])
}
fmt.Println()
for _, r := range s { //rune
fmt.Printf("%v(%c) ", r, r)
}
fmt.Println()
}輸出:
104(h) 101(e) 108(l) 108(l) 111(o) 230(æ) 178(²) 153() 230(æ) 178(²) 179(³)
104(h) 101(e) 108(l) 108(l) 111(o) 27801(你) 27827(好)因為UTF8編碼下一個中文漢字由3~4個字節組成,所以我們不能簡單的按照字節去遍歷一個包含中文的字符串,否則就會出現上面輸出中第一行的結果。
字符串底層是一個byte數組,所以可以和[]byte類型相互轉換。字符串是不能修改的 字符串是由byte字節組成,所以字符串的長度是byte字節的長度。rune類型用來表示utf8字符,一個rune字符由一個或多個byte組成。
修改字符串
要修改字符串,需要先將其轉換成[]rune或[]byte,完成後再轉換為string。無論哪種轉換,都會重新分配內存,並複製字節數組。
func changeString() {
s1 := "big"
// 強制類型轉換
byteS1 := []byte(s1)
byteS1[0] = 'p'
fmt.Println(string(byteS1))
s2 := "白蘿蔔"
runeS2 := []rune(s2)
runeS2[0] = '紅'
fmt.Println(string(runeS2))
}
類型轉換
Go語言中只有強制類型轉換,沒有隱式類型轉換。該語法只能在兩個類型之間支持相互轉換的時候使用。
強制類型轉換的基本語法如下:
T(表達式)其中,T表示要轉換的類型。表達式包括變量、複雜算子和函數返回值等.
比如計算直角三角形的斜邊長時使用math包的Sqrt()函數,該函數接收的是float64類型的參數,而變量a和b都是int類型的,這個時候就需要將a和b強制類型轉換為float64類型。
func sqrtDemo() {
var a, b = 3, 4
var c int
// math.Sqrt()接收的參數是float64類型,需要強制轉換
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
}