go學習筆記1

hello GO

這裏使用vscodelinux

  1. 安裝插件go編程

  2. 新建hello文件夾,建立main.go文件windows

    package main
    import "fmt"
    func main(){
    	fmt.Println("Hello")
    }
    1. 打開命令行數組

      image-20200827134240655

  3. 執行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

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語言支持兩種浮點型數:float32float64

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(假)兩個值。

注意:

  1. 布爾類型變量的默認值爲false
  2. Go 語言中不容許將整型強制轉換爲布爾型.
  3. 布爾型沒法參與數值運算,也沒法與其餘類型進行轉換。

字符串

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操做

byte和rune類型

字符用單引號(’)包裹起來

  1. nt8類型,或者叫 byte 型,表明了ASCII碼的一個字符。
  2. 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. 算術運算符 + - * / %

  2. 關係運算符 == != > >= < <=

  3. 邏輯運算符 && || !

  4. 位運算符

    運算符 描述
    & 參與運算的兩數各對應的二進位相與。 (兩位均爲1才爲1)
    | 參與運算的兩數各對應的二進位相或。 (兩位有一個爲1就爲1)
    ^ 參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果爲1。 (兩位不同則爲1)
    << 左移n位就是乘以2的n次方。 「a<<b」是把a的各二進位所有左移b位,高位丟棄,低位補0。
    >> 右移n位就是除以2的n次方。 「a>>b」是把a的各二進位所有右移b位。
  5. 賦值運算符 = += -= *= /= %= <<= >>= &= |= ^=

流程控制

ifelse

if 表達式1 {
    分支1
} else if 表達式2 {
    分支2
} else{
    分支3
}

for

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 {
    循環體語句
}

for range(鍵值循環)

switch case

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

goto

經過標籤進行代碼間的無條件跳轉

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(跳出循環)

break語句能夠結束forswitchselect的代碼塊。

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("...")
}

continue(繼續下次循環)

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]]
}

注意:

  1. 數組支持 「==「、」!=」 操做符,由於內存老是被初始化過的。
  2. [n]*T表示指針數組,*[n]T表示數組指針 。

切片

一個擁有相同類型元素的可變長度的序列

定義

var name []T

長度/容量

經過使用內置的len()函數求長度,使用內置的cap()函數求切片的容量

len(s), cap(s)
使用make()函數建立構造切片
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共用一個底層數組
切片遍歷

遍歷方式和數組是一致的

append
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
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

map定義
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("查無此人")
	}
}
map遍歷
func main() {
	scoreMap := make(map[string]int)
	scoreMap["張三"] = 90
	scoreMap["小明"] = 100
	scoreMap["娜扎"] = 60
	for k, v := range scoreMap {
		fmt.Println(k, v)
	}
}

遍歷map時的元素順序與添加鍵值對的順序無關。

delete
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)
	}
}
按照指定順序遍歷map
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])
	}
}
元素爲map類型的切片
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)
	}
}
值爲切片類型的map
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

相關文章
相關標籤/搜索