這裏使用vscodelinux
安裝插件go編程
新建hello文件夾,建立main.go文件windows
package main import "fmt" func main(){ fmt.Println("Hello") }
打開命令行數組
執行go build 這時同目錄會建立一個hello.exe的文件(我這裏使用的是win電腦)bash
也可使用 go build -o aaa.exe 指定文件名架構
也直接輸出可以使用 go run main.goapp
只須要指定目標操做系統的平臺和處理器架構便可:編程語言
SET CGO_ENABLED=0 // 禁用CGO SET GOOS=linux // 目標平臺是linux SET GOARCH=amd64 // 目標處理器架構是amd64
而後再執行go build
命令,獲得的就是可以在Linux平臺運行的可執行文件了。函數
Mac 下編譯 Linux 和 Windows平臺 64位 可執行程序:oop
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build
Linux 下編譯 Mac 和 Windows 平臺64位可執行程序:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build
Windows下編譯Mac平臺64位可執行程序:
SET CGO_ENABLED=0 SET GOOS=darwin SET GOARCH=amd64 go build
//單行註釋
/*
多行註釋
*/
fmt.Println('打印輸出')
一行代碼不需加分號
變量聲明後必須使用,不使用會報錯
縮進沒有嚴格要求
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
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
聲明: var 變量名 變量類型
單個聲明 var aaa string var age int var iss bool 批量聲明 var ( a string b int c bool )
變量初始化: var 變量名 類型 = 表達式
var name string = "aa" 一次初始化多個變量 var name,age = "bb",20
短變量聲明(聲明並初始化) :=
n:=10 m:=50
匿名變量:用一個下劃線_
表示
匿名變量不佔用命名空間,不會分配內存,因此匿名變量之間不存在重複聲明。 (在Lua
等編程語言裏,匿名變量也被叫作啞元變量。)
func foo() (int, string) { return 10, "Q1mi" } func main() { x, _ := foo() _, y := foo() fmt.Println("x=", x) fmt.Println("y=", y) }
注意:
函數外的每一個語句都必須以關鍵字開始(var、const、func等)
:=
不能使用在函數外。
_
多用於佔位,表示忽略值。
const a = 'dsadasd'
和變量相似
const ( a string b int c bool )
iota : go語言的常量計數器
iota
在const關鍵字出現時將被重置爲0
const ( n1 = iota //0 n2 //1 n3 //2 n4 //3 ) 使用_調過某些值 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
多個iota
定義在一行
const ( a, b = iota + 1, iota + 2 //1,2 c, d //2,3 e, f //3,4 )
Go語言中有豐富的數據類型,除了基本的整型、浮點型、布爾型、字符串外,還有數組、切片、結構體、函數、map、通道(channel)等。
類型 | 描述 |
---|---|
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) |
特殊整型
類型 | 描述 |
---|---|
uint | 32位操做系統上就是uint32 ,64位操做系統上就是uint64 |
int | 32位操做系統上就是int32 ,64位操做系統上就是int64 |
uintptr | 無符號整型,用於存放一個指針 |
進制
// 十進制 var a int = 10 fmt.Printf("%d \n", a) // 10 fmt.Printf("%b \n", a) // 1010 佔位符%b表示二進制 // 八進制 以0開頭 var b int = 077 fmt.Printf("%o \n", b) // 77 // 十六進制 以0x開頭 var c int = 0xff fmt.Printf("%x \n", c) // ff fmt.Printf("%X \n", c) // FF
Go語言支持兩種浮點型數:float32
和float64
package main import ( "fmt" "math" ) func main() { fmt.Printf("%f\n", math.Pi) fmt.Printf("%.2f\n", math.Pi) }
complex64和complex128
複數有實部和虛部,complex64的實部和虛部爲32位,complex128的實部和虛部爲64位。
var c1 complex64 c1 = 1 + 2i var c2 complex128 c2 = 2 + 3i fmt.Println(c1) fmt.Println(c2)
Go語言中以bool
類型進行聲明布爾型數據,布爾型數據只有true(真)
和false(假)
兩個值。
注意:
false
。s1 := "hello" s2 := "你好"
字符串轉義符
轉義符 | 含義 |
---|---|
\r |
回車符(返回行首) |
\n |
換行符(直接跳到下一行的同列位置) |
\t |
製表符 |
\' |
單引號 |
\" |
雙引號 |
\\ |
反斜槓 |
多行字符串 使用反引號
字符串的經常使用操做
方法 | 介紹 |
---|---|
len(str) | 求長度 |
+或fmt.Sprintf | 拼接字符串 |
strings.Split | 分割 |
strings.contains | 判斷是否包含 |
strings.HasPrefix,strings.HasSuffix | 前綴/後綴判斷 |
strings.Index(),strings.LastIndex() | 子串出現的位置 |
strings.Join(a[]string, sep string) | join操做 |
字符用單引號(’)包裹起來
nt8
類型,或者叫 byte 型,表明了ASCII碼
的一個字符。rune
類型,表明一個 UTF-8字符
。當須要處理中文、日文或者其餘複合字符時,則須要用到rune
類型。rune
類型實際是一個int32
修改字符串
要修改字符串,須要先將其轉換成[]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)) }
強制轉換
T(表達式) T表示要轉換的類型。表達式包括變量、複雜算子和函數返回值等.
算術運算符 + - * / %
關係運算符 == != > >= < <=
邏輯運算符 && || !
位運算符
運算符 | 描述 |
---|---|
& | 參與運算的兩數各對應的二進位相與。 (兩位均爲1才爲1) |
| | 參與運算的兩數各對應的二進位相或。 (兩位有一個爲1就爲1) |
^ | 參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果爲1。 (兩位不同則爲1) |
<< | 左移n位就是乘以2的n次方。 「a<<b」是把a的各二進位所有左移b位,高位丟棄,低位補0。 |
>> | 右移n位就是除以2的n次方。 「a>>b」是把a的各二進位所有右移b位。 |
賦值運算符 = += -= *= /= %= <<= >>= &= |= ^=
if 表達式1 { 分支1 } else if 表達式2 { 分支2 } else{ 分支3 }
for 初始語句;條件表達式;結束語句{ 循環體語句 }
完整 func forDemo() { for i := 0; i < 10; i++ { fmt.Println(i) } } 初始語句省略 func forDemo2() { i := 0 for ; i < 10; i++ { fmt.Println(i) } } 初始語句/結束語句結束 func forDemo3() { i := 0 for i < 10 { fmt.Println(i) i++ } } 無限循環 for { 循環體語句 }
func switchDemo1() { finger := 3 switch finger { case 1: fmt.Println("大拇指") case 2: fmt.Println("食指") case 3: fmt.Println("中指") case 4: fmt.Println("無名指") case 5: fmt.Println("小拇指") default: fmt.Println("無效的輸入!") } } func testSwitch3() { switch n := 7; n { case 1, 3, 5, 7, 9: fmt.Println("奇數") case 2, 4, 6, 8: fmt.Println("偶數") default: fmt.Println(n) } }
fallthrough
語法能夠執行知足條件的case的下一個case,是爲了兼容C語言中的case設計的。
func switchDemo5() { s := "a" switch { case s == "a": fmt.Println("a") fallthrough case s == "b": fmt.Println("b") case s == "c": fmt.Println("c") default: fmt.Println("...") } } 輸出: a b
經過標籤進行代碼間的無條件跳轉
func gotoDemo2() { for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { // 設置退出標籤 goto breakTag } fmt.Printf("%v-%v\n", i, j) } } return // 標籤 breakTag: fmt.Println("結束for循環") }
break
語句能夠結束for
、switch
和select
的代碼塊。
func breakDemo1() { BREAKDEMO1: for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { break BREAKDEMO1 } fmt.Printf("%v-%v\n", i, j) } } fmt.Println("...") }
func continueDemo() { forloop1: for i := 0; i < 5; i++ { // forloop2: for j := 0; j < 5; j++ { if i == 2 && j == 2 { continue forloop1 } fmt.Printf("%v-%v\n", i, j) } } }
var 數組變量名 [元素數量]T
一旦定義,長度不能變
func main() { var testArray [3]int //數組會初始化爲int類型的零值 var numArray = [3]int{1, 2} //使用指定的初始值完成初始化 var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化 fmt.Println(testArray) //[0 0 0] fmt.Println(numArray) //[1 2 0] fmt.Println(cityArray) //[北京 上海 深圳] }
func main() { var testArray [3]int var numArray = [...]int{1, 2} var cityArray = [...]string{"北京", "上海", "深圳"} fmt.Println(testArray) //[0 0 0] fmt.Println(numArray) //[1 2] fmt.Printf("type of numArray:%T\n", numArray) //type of numArray:[2]int fmt.Println(cityArray) //[北京 上海 深圳] fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string }
func main() { a := [...]int{1: 1, 3: 5} fmt.Println(a) // [0 1 0 5] fmt.Printf("type of a:%T\n", a) //type of a:[4]int }
func main() { var a = [...]string{"北京", "上海", "深圳"} // 方法1:for循環遍歷 for i := 0; i < len(a); i++ { fmt.Println(a[i]) } // 方法2:for range遍歷 for index, value := range a { fmt.Println(index, value) } }
func main() { a := [3][2]string{ {"北京", "上海"}, {"廣州", "深圳"}, {"成都", "重慶"}, } for _, v1 := range a { for _, v2 := range v1 { fmt.Printf("%s\t", v2) } fmt.Println() } } 北京 上海 廣州 深圳 成都 重慶
多維數組只有第一層可使用...
來讓編譯器推導數組長度。例如:
//支持的寫法 a := [...][2]string{ {"北京", "上海"}, {"廣州", "深圳"}, {"成都", "重慶"}, } //不支持多維數組的內層使用... b := [3][...]string{ {"北京", "上海"}, {"廣州", "深圳"}, {"成都", "重慶"}, }
數組是值類型,賦值和傳參會複製整個數組。所以改變副本的值,不會改變自己的值。
func modifyArray(x [3]int) { x[0] = 100 } func modifyArray2(x [3][2]int) { x[2][0] = 100 } func main() { a := [3]int{10, 20, 30} modifyArray(a) //在modify中修改的是a的副本x fmt.Println(a) //[10 20 30] b := [3][2]int{ {1, 1}, {1, 1}, {1, 1}, } modifyArray2(b) //在modify中修改的是b的副本x fmt.Println(b) //[[1 1] [1 1] [1 1]] }
注意:
[n]*T
表示指針數組,*[n]T
表示數組指針 。一個擁有相同類型元素的可變長度的序列
var name []T
經過使用內置的len()
函數求長度,使用內置的cap()
函數求切片的容量
len(s), cap(s)
make([]T, size, cap) T:切片的元素類型 size:切片中元素的數量 cap:切片的容量 a := make([]int, 2, 10) fmt.Println(a) //[0 0] fmt.Println(len(a)) //2 fmt.Println(cap(a)) //10
請始終使用len(s) == 0
來判斷,而不該該使用s == nil
來判斷。
s1 := make([]int, 3) //[0 0 0] s2 := s1 //將s1直接賦值給s2,s1和s2共用一個底層數組
遍歷方式和數組是一致的
func main(){ var s []int s = append(s, 1) // [1] s = append(s, 2, 3, 4) // [1 2 3 4] s2 := []int{5, 6, 7} s = append(s, s2...) // [1 2 3 4 5 6 7] }
var聲明的零值切片能夠在append()
函數直接使用,無需初始化。
s := []int{} // 沒有必要初始化 s = append(s, 1, 2, 3) var s = make([]int) // 沒有必要初始化 s = append(s, 1, 2, 3)
追加切片
var citySlice []string // 追加一個元素 citySlice = append(citySlice, "北京") // 追加多個元素 citySlice = append(citySlice, "上海", "廣州", "深圳") // 追加切片 a := []string{"成都", "重慶"} citySlice = append(citySlice, a...) fmt.Println(citySlice) //[北京 上海 廣州 深圳 成都 重慶]
copy(destSlice, srcSlice []T) srcSlice: 數據來源切片 destSlice: 目標切片
func main() { // copy()複製切片 a := []int{1, 2, 3, 4, 5} c := make([]int, 5, 5) copy(c, a) //使用copy()函數將切片a中的元素複製到切片c fmt.Println(a) //[1 2 3 4 5] fmt.Println(c) //[1 2 3 4 5] c[0] = 1000 fmt.Println(a) //[1 2 3 4 5] fmt.Println(c) //[1000 2 3 4 5] }
沒有刪除切片元素的專用方法,咱們可使用切片自己的特性來刪除元素
從切片a中刪除索引爲index
的元素,操做方法是a = append(a[:index], a[index+1:]...)
func main() { // 從切片中刪除元素 a := []int{30, 31, 32, 33, 34, 35, 36, 37} // 要刪除索引爲2的元素 a = append(a[:2], a[3:]...) fmt.Println(a) //[30 31 33 34 35 36 37] }
map[KeyType]ValueType KeyType:表示鍵的類型。 ValueType:表示鍵對應的值的類型。
map類型的變量默認初始值爲nil,須要使用make()函數來分配內存。語法爲:
make(map[KeyType]ValueType, [cap])
func main() { scoreMap := make(map[string]int, 8) scoreMap["張三"] = 90 scoreMap["小明"] = 100 fmt.Println(scoreMap) fmt.Println(scoreMap["小明"]) fmt.Printf("type of a:%T\n", scoreMap) } map[小明:100 張三:90] 100 type of a:map[string]int map也支持在聲明的時候填充元素 func main() { userInfo := map[string]string{ "username": "沙河小王子", "password": "123456", } fmt.Println(userInfo) // }
value, ok := map[key]
func main() { scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["小明"] = 100 // 若是key存在ok爲true,v爲對應的值;不存在ok爲false,v爲值類型的零值 v, ok := scoreMap["張三"] if ok { fmt.Println(v) } else { fmt.Println("查無此人") } }
func main() { scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["小明"] = 100 scoreMap["娜扎"] = 60 for k, v := range scoreMap { fmt.Println(k, v) } }
遍歷map時的元素順序與添加鍵值對的順序無關。
delete(map, key)
func main(){ scoreMap := make(map[string]int) scoreMap["張三"] = 90 scoreMap["小明"] = 100 scoreMap["娜扎"] = 60 delete(scoreMap, "小明")//將小明:100從map中刪除 for k,v := range scoreMap{ fmt.Println(k, v) } }
func main() { rand.Seed(time.Now().UnixNano()) //初始化隨機數種子 var scoreMap = make(map[string]int, 200) for i := 0; i < 100; i++ { key := fmt.Sprintf("stu%02d", i) //生成stu開頭的字符串 value := rand.Intn(100) //生成0~99的隨機整數 scoreMap[key] = value } //取出map中的全部key存入切片keys var keys = make([]string, 0, 200) for key := range scoreMap { keys = append(keys, key) } //對切片進行排序 sort.Strings(keys) //按照排序後的key遍歷map for _, key := range keys { fmt.Println(key, scoreMap[key]) } }
func main() { var mapSlice = make([]map[string]string, 3) for index, value := range mapSlice { fmt.Printf("index:%d value:%v\n", index, value) } fmt.Println("after init") // 對切片中的map元素進行初始化 mapSlice[0] = make(map[string]string, 10) mapSlice[0]["name"] = "小王子" mapSlice[0]["password"] = "123456" mapSlice[0]["address"] = "沙河" for index, value := range mapSlice { fmt.Printf("index:%d value:%v\n", index, value) } }
func main() { var sliceMap = make(map[string][]string, 3) fmt.Println(sliceMap) fmt.Println("after init") key := "中國" value, ok := sliceMap[key] if !ok { value = make([]string, 0, 2) } value = append(value, "北京", "上海") sliceMap[key] = value fmt.Println(sliceMap)
高顏值後臺管理系統無償使用 ### 子楓後臺管理系統 ###,可在寶塔面板直接安裝
歡迎關注個人公衆號:子楓的奇妙世界,得到獨家整理的學習資源和平常乾貨推送。
若是您對個人其餘專題內容感興趣,直達個人我的博客:www.wangmingchang.com 。