Go 編程快速入門學習
0x00 Go 語言基礎之變量和常量
-
- 標識符
-
- 關鍵字
-
- 變量 - Var
-
變量聲明
-
變量初始化
-
匿名變量
-
- 常量 - Const
-
iota - 常量計數器
0x01 Go 語言基礎之基本數據類型
-
- 整型
-
特殊整型
-
數字字面量語法(Number literals syntax)
-
- 浮點型
-
- 複數
-
- 布爾值
-
- 字符串
-
字符串轉義符
-
多行字符串
-
字符串的常用操作
-
6.byte 和 rune 類型
-
- 類型轉換
0x02 Go 語言基礎之運算符
-
- 分類說明
-
- 算術運算符
-
- 關係運算符
-
- 邏輯運算符
-
- 位運算符
0x03 Go 語言基礎之流程控制
-
1.if else(分支結構)
-
if 條件判斷基本寫法
-
if 條件判斷特殊寫法
-
2.for(循環結構)
-
3.for range(鍵值循環)
-
4.switch case(選擇語句)
-
5.goto(跳轉到指定標籤)
-
6.break(跳出循環)
-
7.continue(繼續下次循環)
0x00 Go 語言基礎之變量和常量
描述: 變量和常量是編程中必不可少的部分,也是很好理解的一部分。
1. 標識符
描述: 在編程語言中標識符就是程序員定義的具有特殊意義的詞,比如變量名、常量名、函數名
等等。 Go 語言中標識符由字母數字和_(下劃線)組成,並且只能以字母和_開頭。 舉幾個例子:abc, _, _123, a123
。
編程語言中常用的三種命名規則,而 Go 語言推薦使用駝峯法式命名。
# 下劃線連接
student_name
# 小駝峯法式 (推薦方式)
studentName
# 大駝峯法式
StudentName
2. 關鍵字
描述: 關鍵字是指編程語言中預先定義好的具有特殊含義的標識符。 關鍵字和保留字都不建議用作變量名。
- Go 語言中有 25 個關鍵字:
* var const : 變量和常量的聲明
* var varName type 或者 varName : = value
* package and import: 導入
* func: 用於定義函數和方法
* return :用於從函數返回
* defer someCode :在函數退出之前執行
* go : 用於並行
* select 用於選擇不同類型的通訊
* interface 用於定義接口
* struct 用於定義抽象數據類型
* break、case、continue、for、fallthrough、else、if、switch、goto、default 流程控制
* chan 用於channel通訊
* type 用於聲明自定義類型
* map 用於聲明map類型數據
* range 用於讀取slice、map、channel數據
- 此外 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
3. 變量 - Var
Q: 變量的來歷?
答: 程序運行過程中的數據都是保存在內存中,我們想要在代碼中操作某個數據時就需要去內存上找到這個變量,但是如果我們直接在代碼中通過內存地址去操作變量的話,代碼的可讀性會非常差而且還容易出錯,所以我們就利用變量將這個數據的內存地址保存起來,以後直接通過這個變量就能找到內存上對應的數據了。
Q: 變量類型
答: 變量(Variable)的功能是存儲數據。不同的變量保存的數據類型可能會不一樣。經過半個多世紀的發展,編程語言已經基本形成了一套固定的類型,常見變量的數據類型有:整型、浮點型、布爾型等。
Tips : 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 = "WeiyiGeek"
var age int = 18
//# 批量變量初始化
var name, age = "WeiyiGeek", 20
類型推導
描述: 有時候我們會將變量的類型省略,這個時候編譯器會根據等號右邊的值來推導變量的類型完成初始化。
var name = "WeiyiGeek"
var age = 18
短變量聲明
描述: 在函數內部可以使用更簡略的:=
方式聲明並初始化變量。
func main() {
count := 10
username := "WeiyiGeek"
}
匿名變量
描述: 在使用多重賦值時,如果想要忽略某個值
,可以使用匿名變量(anonymous variable)- 特殊變量
。並且匿名變量不佔用命名空間,不會分配內存,所以匿名變量之間不存在重複聲明。 (在Lua等編程語言裏,匿名變量也被叫做啞元變量。
)
匿名變量用一個下劃線(_)
表示,例如:
func foo() (int, string) {
return 10, "Q1mi"
}
func main() {
x, _ := foo()
_, y := foo()
fmt.Println("x=", x)
fmt.Println("y=", y)
}
示例演示:
package main
import "fmt"
// 變量聲明(單一-全局)
var singleName string
var notUseVar bool
// 變量聲明(批量-全局)
var (
multiName string
multiAge int8
)
func main() {
// 對聲明後的變量賦值
singleName = "Weiyi_"
multiName = "Geek"
multiAge = 18
// 變量初始化(局部)
var name string = "WeiyiGeek"
var sex, addr = "boy", "China"
// 類型推導變量
var flag = true
var count = 1024
// 簡短變量聲明(此種類型只能在函數中使用)
briefCount := 65535
fmt.Printf("My Name is %s, Sex is %s , Address: %s\n", name, sex, addr)
fmt.Println("Alias Name :", singleName, multiName, " Age is :", multiAge)
fmt.Print("類型推導 :", flag, count)
fmt.Println(", 簡短變量 :", briefCount)
}
輸出結果:
API server listening at: 127.0.0.1:42954
My Name is WeiyiGeek, Sex is boy , Address: China
Alias Name : Weiyi_ Geek Age is : 18
類型推導 :true 1024, 簡短變量 : 65535
Tips : Go 語言中變量必須先聲明後使用,而且聲明變量(非全局變量)
後必須使用,如有不使用的變量編譯時報錯。
Tips :函數外的每個語句都必須以關鍵字開始 (var、const、func
) 等
Tips : :=
不能使用在函數外。
Tips : 匿名變量或者叫啞元變量(_)
多用於佔位,表示忽略值,即當有些數據必須用變量接收但又不使用它時,可以採用_來接收改值。
Tips : 變量在同一個作用域中代碼塊({})
中不能重複聲明同名的變量。
4. 常量 - Const
描述: 常量是在程序運行期間恆定不變的值,多用於定義程序運行期間不會改變的那些值。常量的聲明和變量聲明非常類似,只是把var換成了const
,常量在定義的時候必須賦值。
常量聲明初始化格式:
// 單一聲明: 聲明瞭pi和e這兩個常量之後,在整個程序運行期間它們的值都不能再發生變化了。
const pi = 3.1415
const e = 2.7182
// 批量聲明
const (
pi = 3.1415
e = 2.7182
)
// 批量聲明(如果省略了值則表示和上面一行的值相同)
// 常量n1、n2、n3的值都是100。
const (
n1 = 100
n2
n3
)
iota - 常量計數器
描述: iota 是 go 語言的常量計數器,只能在常量的表達式中使用。
Tips : iota 在 const 關鍵字出現時將被重置爲 0, const 中每新增一行常量聲明將使 iota 計數一次 (iota可理解爲const語句塊中的行索引
)。
應用場景: 使用 iota 能簡化定義,在定義枚舉時很有用。
下面示例中幾個常見的 iota 示例:
-
- 使用
_
跳過某些值
- 使用
const (
n1 = iota //0
n2 //1
_
n4 //3
)
- 2.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
)
-
- 定義數量級 (這裏的 << 表示左移操作,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)
)
示例演示:
package main
import "fmt"
// 單一常量聲明
const pi = 3.1415926535898
// 批量常量聲明
const (
e = 2.7182
flag = false
)
// 特殊批量常量聲明
const (
a = 1
b
_
c
)
// iota 常量計數器
const (
_ = iota // 0
d, e1 = iota + 1, iota + 2 // 2,3 常量名稱不能重複
f, g = iota + 1, iota + 2 // 3,4
)
const (
_ = iota // 0
KB = 1 << (10 * iota) // 1024
MB = 1 << (10 * iota)
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)
func main() {
fmt.Println("pi :", pi)
fmt.Println("e :", e, " , flag:", false)
fmt.Println("特殊批量常量聲明:", a, b, c)
fmt.Println("iota 常量計數器 :", d, e1, f, g)
fmt.Println("文件體積大小 :", KB, MB, GB, TB, PB)
}
執行結果:
pi : 3.1415926535898
e : 2.7182 , flag: false
特殊批量常量聲明: 1 1 1
iota 常量計數器 : 2 3 3 4
文件體積大小 : 1024 1048576 1073741824 1099511627776 1125899906842624
Tips : 常量聲明後不能在程序中進行重新賦值更改。
0x01 Go 語言基礎之基本數據類型
基本數據類型:
Go 語言中有豐富的數據類型,除了基本的整型、浮點型、布爾型、字符串外,還有數組、切片、結構體、函數、map、通道(channel)等。
Tips : Go 語言的基本類型和其他語言大同小異。
1. 整型
整型分爲以下兩個大類: 按長度分爲:int8、int16、int32、int64
對應的無符號整型:uint8、uint16、uint32、uint64
其中,uint8
就是我們熟知的byte
型,int16
對應 C 語言中的short
型,int64
對應 C 語言中的long
型。
特殊整型
注意: 在使用int
和 uint
類型時,不能假定它是 32 位或 64 位的整型,而是考慮int
和uint
可能在不同平臺上的差異。
注意事項: 獲取對象的長度的內建len()
函數返回的長度可以根據不同平臺的字節長度進行變化。實際使用中,切片或 map 的元素數量等都可以用int
來表示。在涉及到二進制傳輸、讀寫文件的結構描述時,爲了保持文件的結構不會受到不同編譯目標平臺字節長度的影響,不要使用int
和 uint
。
數字字面量語法(Number literals syntax)
Go1.13 版本之後引入了數字字面量語法,這樣便於開發者以二進制、八進制或十六進制浮點數
的格式定義數字,例如:
-
v := 0b00101101
, 代表二進制的 101101,相當於十進制的 45。 -
v := 0o377
,代表八進制的 377,相當於十進制的 255。
- v := 0x1p-2
,代表十六進制的 1 除以 2²,也就是 0.25。
而且還允許我們用 _
來分隔數字,比如說: v := 123_456
表示 v 的值等於 123456。
簡單示例: 我們可以藉助 fmt 函數來將一個整數以不同進制形式展示。
package main
import "fmt"
func main(){
// 十進制以不同的進制展示
var a int = 10
fmt.Printf("%b \n", a) // 1010 佔位符%b表示二進制
fmt.Printf("%o \n", a) // 12 佔位符%o表示八進制
fmt.Printf("%d \n", a) // 10 佔位符%d表示十進制
fmt.Printf("0x%x \n", a) // 0xa 佔位符%x表示十六進制
// 八進制(以0開頭)
var b int = 077
fmt.Printf("%b \n", b) // 111111
fmt.Printf("%o \n", b) // 77
fmt.Printf("%d \n", b) // 63
fmt.Printf("0x%x \n", b) // 0x3f
// 十六進制(以0x開頭)
var c int = 0xff
fmt.Printf("0x%x \n", c) // 0xff
fmt.Printf("0X%X \n", c) // 0xFF
// 數字字面量語法(Number literals syntax)
binary := 0b1111
octal := 0o17
digital := 15
hexadecimal := 0xf
specialhexa := 0x8p-2 // 8 / 2^2 = 2
underline := 10_24
fmt.Printf("binary : %b , digital : %d\n", binary, binary)
fmt.Printf("octal : %o , digital : %d\n", octal, octal)
fmt.Printf("digital type (變量類型): %T,digital : %d\n", digital, digital)
fmt.Printf("hexadecimal : %x, digital : %d, specialhexa : %f\n", hexadecimal, hexadecimal, specialhexa)
fmt.Printf("underline : %d \n", underline)
}
輸出結果:
# Int 整型示例:
1010
12
10
0xa
111111
77
63
0x3f
0xff
0XFF
binary : 1111 , digital : 15
octal : 17 , digital : 15
digital type (變量類型): int,digital : 15
2. 浮點型
Go 語言支持兩種浮點型數:float32
和float64
。
這兩種浮點型數據格式遵循IEEE 754
標準:
-
float32
的浮點數的最大範圍約爲3.4e38
,其常量定義:math.MaxFloat32
。 -
float64
的浮點數的最大範圍約爲1.8e308
,其常量定義:math.MaxFloat64
。
簡單示例: 打印浮點數時,可以使用fmt
包配合動詞%f
,代碼如下:
package main
import (
"fmt"
"math"
)
func main() {
var floatnumber float64 = 1024.00
fmt.Printf("數據類型: %T , floatnumber: %.1f\n", floatnumber, floatnumber)
fmt.Printf("%f,%.2f\n", math.Pi, math.Pi) // 保留小數點後兩位
fmt.Printf("float32的浮點數的最大範圍 :%d ~ %f\n", 0, math.MaxFloat32)
fmt.Printf("float64的浮點數的最大範圍 :%d ~ %f\n", 0, math.MaxFloat64)
}
執行結果:
數據類型: float64 , floatnumber: 1024.0
3.141593,3.14
float32的浮點數的最大範圍 :0 ~ 340282346638528859811704183484516925440.000000
float64的浮點數的最大範圍 :0 ~ 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
3. 複數
描述: 複數有實部和虛部,complex64 的實部和虛部爲 32 位,complex128 的實部和虛部爲 64 位。
例如: complex64 和 complex128 類型變量輸出示例
var c1 complex64
c1 = 1 + 2i
var c2 complex128
c2 = 2 + 3i
fmt.Println(c1) // (1+2i)
fmt.Println(c2) // (2+3i)
4. 布爾值
Go 語言中以bool
類型進行聲明布爾型數據,布爾型數據只有true(真)
和false(假)
兩個值。
fmt.Println("# 4.布爾型示例:")
var flag bool = true
fmt.Printf("數據類型: %T ,任意類型輸出: %v", flag, flag) // 數據類型: bool ,任意類型輸出: true
注意:
-
布爾類型變量的默認值爲
false
。 -
Go 語言中不允許將整型強制轉換爲布爾型.
-
布爾型無法參與數值運算,也無法與其他類型進行轉換。
5. 字符串
描述: Go 語言中的字符串以原生數據類型
出現,使用字符串就像使用其他原生數據類型(int、bool、float32、float64 等)一樣。
Go 語言裏的字符串的內部實現使用UTF-8
編碼。 字符串的值爲雙引號(")
中的內容,可以在 Go 語言的源碼中直接添加非 ASCII 碼字符,例如:
s1 := "hello"
s2 := "你好"
c1 := 'g'
c2 := 'o'
Tips : Go 語言中用雙引號包裹的是字符串
,而單引號包裹的是字符
。
字符串轉義符
Go 語言的字符串常見轉義符包含回車、換行、單雙引號、製表符等,如下表所示。
舉個例子,我們要打印一個 Windows 平臺下的一個文件路徑:
package main
import (
"fmt"
)
func main() {
s1 := "'c:\\weiyigeek\\go\\hello'"
fmt.Println("str :=",s1)
fmt.Println("str := \"c:\\Code\\weiyigeek\\go.exe\"")
}
多行字符串
Go 語言中要定義一個多行字符串時,就必須使用反引號
字符:
s1 := `第一行
第二行
第三行
`
s2 := `c:\weiyigeek\go\hello` // 注意點此處沒用轉義符(\) 也能輸出路徑
fmt.Println(s1,s2)
Tips: 反引號間換行將被作爲字符串中的換行,但是所有的轉義字符均無效,文本將會原樣輸出。
字符串的常用操作
示例演示:
// 字符串型示例
func stringdemo() {
// 字符
c1 := 'a'
c2 := 'A'
// 字符串 (單行與多行以及轉義)
s1 := "Name"
s2 := "姓名"
s3 := `
這是一個
多行字符串案例!
This is mutlilineString Example!
Let's Go // 特點:原樣輸出
`
// 轉義演示
s4 := "'c:\\weiyigeek\\go\\hello'"
s5 := `c:\weiyigeek\go\hello`
fmt.Printf("c1 char : %c,\t c2 char %c -> digital : %d\n", c1, c2, c2)
fmt.Println(s1, s2)
fmt.Println(s3)
fmt.Println(s4, s5)
// 字符串常用函數
fmt.Println("s1 String length:", len(s1), "s2 string length:", len(s2))
info := fmt.Sprintf("%s (%s): %s", s1, s2, "WeiyiGeek")
fmt.Println("Infomation : "+"個人信息", info)
fmt.Println("字符串分割 :", strings.Split(s5, "\\"))
fmt.Println("判斷字符串是否包含go", strings.Contains(s3, "go"))
fmt.Println(strings.HasPrefix(s1, "N"), strings.HasSuffix(s1, "e"))
fmt.Println(strings.Index(s4, "weiyigeek"), strings.LastIndex(s4, "weiyigeek"))
s6 := strings.Split(s5, "\\")
fmt.Println("字符串間隔符 : ", strings.Join(s6, "-"))
}
執行效果:
# 5.字符串型示例:
c1 char : a, c2 char A -> digital : 65
Name 姓名
這是一個
多行字符串案例!
This is mutlilineString Example!
Let's Go // 特點:原樣輸出
'c:\weiyigeek\go\hello' c:\weiyigeek\go\hello
s1 String length: 4 s2 string length: 6
Infomation : 個人信息 Name (姓名): WeiyiGeek
字符串分割 : [c: weiyigeek go hello]
判斷字符串是否包含go false
true true
4 4
字符串間隔符 : c:-weiyigeek-go-hello
6.byte 和 rune 類型
描述: 組成每個字符串的元素叫做 “字符”,可以通過遍歷或者單個獲取字符串元素獲得字符。 字符用單引號(’)包裹起來,如:
var a = '中'
var b = 'x'
c := 'a'
Go 語言的字符有以下兩種:
-
uint8
類型,或者叫 byte 型,代表了ASCII碼
的一個字符(1B)。 -
rune
類型,代表一個UTF-8字符
, 並且一個 rune 字符由一個或多個 byte 組成(3B~4B)。
Tips : 當需要處理中文、日文或者其他複合字符時,則需要用到rune
類型。rune
類型實際是一個int32
。
Go 使用了特殊的 rune 類型來處理 Unicode,讓基於 Unicode 的文本處理更爲方便,也可以使用 byte 型進行默認字符串處理,性能和擴展性都有照顧。
簡單示例:
// 遍歷字符串
func traversalString() {
s := "hello沙河"
// byte 類型
for i := 0; i < len(s); i++ {
fmt.Printf("%v(%c) ", s[i], s[i])
}
fmt.Println()
// rune 類型
for _, r := range s {
fmt.Printf("%v(%c) ", r, r)
}
fmt.Println()
}
結果輸出:
// byte 類型 (中文亂碼)
104(h) 101(e) 108(l) 108(l) 111(o) 230(æ) 178(²) 153() 230(æ) 178(²) 179(³)
// rune 類型 (中文正常)
104(h) 101(e) 108(l) 108(l) 111(o) 27801(沙) 27827(河)
Q: 爲什麼出現上述情況?
答: 因爲 UTF8 編碼下一箇中文漢字由3~4個字節
(4*8bit)組成,所以我們不能簡單的按照字節去遍歷一個包含中文的字符串,否則就會出現上面輸出中第一行的結果。
Tips : 字符串底層是一個 byte 數組,所以可以和[]byte
類型相互轉換。字符串是不能修改的字符串是由 byte 字節組成,所以字符串的長度是 byte 字節的長度。
7. 類型轉換
描述:Go 語言中只有強制類型轉換,沒有隱式類型轉換。該語法只能在兩個類型之間支持相互轉換的時候使用。
強制類型轉換的基本語法如下:
T(表達式) # 其中,T表示要轉換的類型。表達式包括變量、複雜算子和函數返回值等.
Tips : Boolen 類型不能強制轉換爲整型。
整型轉浮點型
比如:計算直角三角形的斜邊長時使用 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)
}
Tips : 在 Go 語言中不同類型的值不能直接賦值,例如 float32 類型變量 a 的值不能直接賦值給 floa64 類型變量 b 的值。
字符串類型轉換
描述: 如果修改字符串,需要先將其轉換成[]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))
}
Tips : 在一個字符串中如果既有中文也存在英文,我們則可以使用byte[]類型
(1B) 來存放 ASCII 碼錶示的字符 (0~255),如果是中文則使用rune[]
(4B) 類型來存放或者週轉。
案例演示:
// Byte與Rune類型示例
func brdemo() {
var c1 = 'a' // int32 類型
var c2 = 'A' // int32 類型
z1 := '中' // int32 類型
z2 := '文' // int32 類型
z3 := "中" // string 類型 (雙引號)
// 字符不同格式輸出
fmt.Printf("字符 :%d (%c) , %d (%c) \n", c1, c1, c2, c2)
fmt.Printf("中文字符 :%d (%v) = %c , %d (%v) = %c \n", z1, z1, z1, z2, z2, z2)
fmt.Printf("單雙引號不同類型 : c1 = %c (%T) , z2 = %c (%T) , z3 = %s (%T) \n", c1, c1, z2, z2, z3, z3)
// 中英文字符串修改
s1 := "a和我都愛中國"
s2 := "爲 Hello 中國 World,Go 語言 學習"
// 將字符類型轉化爲byte類型
c3 := byte(c2)
fmt.Printf("強制轉化類型 : c2 = %c (%T) , byte(c2) = %c (%T) \n", c2, c2, c3, c3)
// 將字符串類型轉化爲string類型
r1 := []rune(s1) // 強制轉化字符串爲一個rune切片
r1[0] = '您' // 注意此處需傳入爲字符
fmt.Println("修改後中文字符串輸出(未類型轉換):", r1)
fmt.Println("修改後中文字符串輸出(已類型轉換):", s1, string(r1)) // 強制轉化rune切片爲字符串
// 將整型轉化成爲浮點數類型
// 計算直角三角形的斜邊長
var a, b = 3, 4
var c int = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println("計算直角三角形的斜邊長 (a=3,b=4) c =", c)
// 統計字符串中中文個數
res := []rune(s2)
reslen := len(res)
count := 0
for i := 0; i < reslen; i++ {
if res[i] > 255 {
count++
}
}
fmt.Printf("字符串:%s (Length = %d),一共有 %d 箇中文字符", s2, reslen, count)
}
執行結果:
# 6.Byte與Rune型示例:
字符 :97 (a) , 65 (A)
中文字符 :20013 (20013) = 中 , 25991 (25991) = 文
單雙引號不同類型 : c1 = a (int32) , z2 = 文 (int32) , z3 = 中 (string)
強制轉化類型 : c2 = A (int32) , byte(c2) = A (uint8)
修改後中文字符串輸出(未類型轉換): [24744 21644 25105 37117 29233 20013 22269]
修改後中文字符串輸出(已類型轉換): a和我都愛中國 您和我都愛中國
計算直角三角形的斜邊長 (a=3,b=4) c = 5
字符串:爲 Hello 中國 World,Go 語言 學習 (Length = 25),一共有 7 箇中文字符
0x02 Go 語言基礎之運算符
什麼是運算符?
答: 運算符用於在程序運行時執行數學或邏輯運算。
1. 分類說明
描述: 與其他編程語言類似 Go 語言內置的運算符有如下幾種
-
算術運算符
-
關係運算符
-
邏輯運算符
-
位運算符
-
賦值運算符
2. 算術運算符
注意: ++
(自增)和--
(自減)在 Go 語言中是單獨的語句,並不是運算符。
3. 關係運算符
Tips : Go 語言是強類型的所以必須相同類型變量才能進行比較。
4. 邏輯運算符
5. 位運算符
描述: 位運算符對整數在內存中的二進制位進行操作。
6. 賦值運算符
簡單示例:
a += 1 // a = a + 1
a %= 3 // a = a % 3
a <<= 4 // a = a << 4
a ^= 5 // a = a ^ 5
0x03 Go 語言基礎之流程控制
Q: 什麼是流程控制
流程控制是每種編程語言控制邏輯走向和執行次序的重要部分,流程控制可以說是一門語言的 “經脈”。
Tips : Go 語言中最常用的流程控制有if
和for
,而switch
和goto
主要是爲了簡化代碼、降低重複代碼而生的結構,屬於擴展類的流程控制。
1.if else(分支結構)
if 條件判斷基本寫法
描述: Go 語言中if
條件判斷的格式如下:
if 表達式1 {
分支1
} else if 表達式2 {
分支2
} else{
分支3
}
當表達式 1 的結果爲true
時,執行分支 1,否則判斷表達式 2,如果滿足則執行分支 2,都不滿足時,則執行分支 3。 if 判斷中的else if
和else
都是可選的,可以根據實際需要進行選擇。
Go 語言規定與if
匹配的左括號{
必須與if和表達式
放在同一行,{
放在其他位置會觸發編譯錯誤。 同理,與else
匹配的{
也必須與else
寫在同一行,else
也必須與上一個if
或else if
右邊的大括號在同一行。
示例 1:
func ifDemo1() {
score := 65
if score >= 90 {
fmt.Println("A")
} else if score > 75 {
fmt.Println("B")
} else {
fmt.Println("C") // 輸出結果
}
}
if 條件判斷特殊寫法
描述: if 條件判斷還有一種特殊的寫法,可以在 if 表達式之前添加一個執行語句,再根據變量值進行判斷,舉個例子:
示例 2:
func ifDemo2() {
score := 88 // 注意變量作用域的影響
if score := 65; score >= 90 {
fmt.Println("A", score)
} else if score > 75 {
fmt.Println("B", score)
} else {
fmt.Println("C", score) // 輸出結果
}
fmt.Println("score : ", score)
}
執行結果:
C 65
score : 88
思考題: 上下兩種寫法的區別在哪裏?
答: 上述 示例 1 與 示例 2 區別在於定義 score 變量位置得不同, 示例 1 中的 score 變量在函數代碼塊中有效, 而示例 2 中的 score 變量作用域只在
if...else
代碼塊中有效。
2.for(循環結構)
描述: Go 語言中的所有循環類型均可以使用for
關鍵字來完成。
for 循環的基本格式如下:
for 初始語句;條件表達式;結束語句{
循環體語句
}
條件表達式返回true
時循環體不停地進行循環,直到條件表達式返回false
時自動退出循環。
func forDemo() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
for 循環的初始語句可以被忽略,但是初始語句後的分號必須要寫,例如:
func forDemo2() {
i := 0
for ; i < 10; i++ {
fmt.Println(i)
}
}
for 循環的初始語句和結束語句都可以省略,例如:
func forDemo3() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
for 無限循環,這種寫法類似於其他編程語言中的while
,在while
後添加一個條件表達式,滿足條件表達式時持續循環,否則結束循環。
例如: for 循環可以通過break
、goto
、return
、panic
語句強制退出循環。
for {
循環體語句
}
3.for range(鍵值循環)
描述: Go 語言中可以使用for range
遍歷數組、切片、字符串、map 及通道(channel)。
通過for range
遍歷的返回值有以下規律:
-
數組、切片、字符串返回索引和值。
-
map 返回鍵和值。
-
通道(channel)只返回通道內的值。
簡單示例:
s1 := "Hello,Go 輸出的是中文"
for i, v := range s1 {
fmt.Printf("Index : %d ,Value : %s , Number : %v \n", i, string(v), v)
}
輸出結果:
Index : 0 ,Value : H , Number : 72
Index : 1 ,Value : e , Number : 101
Index : 2 ,Value : l , Number : 108
Index : 3 ,Value : l , Number : 108
Index : 4 ,Value : o , Number : 111
Index : 5 ,Value : , , Number : 44
Index : 6 ,Value : G , Number : 71
Index : 7 ,Value : o , Number : 111
Index : 8 ,Value : , Number : 32
Index : 9 ,Value : 輸 , Number : 36755
Index : 12 ,Value : 出 , Number : 20986
Index : 15 ,Value : 的 , Number : 30340
Index : 18 ,Value : 是 , Number : 26159
Index : 21 ,Value : 中 , Number : 20013
Index : 24 ,Value : 文 , Number : 25991
4.switch case(選擇語句)
描述: 使用switch
語句可方便地對大量的值進行條件判斷,即簡化大量判斷。
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("無效的輸入!")
}
}
Go 語言規定每個switch
只能有一個default
分支, 但一個分支可以有多個值,多個 case 值中間使用英文逗號分隔。
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)
}
}
分支還可以使用表達式,這時候 switch 語句後面不需要再跟判斷變量。例如:
func switchDemo4() {
age := 30
switch {
case age < 25:
fmt.Println("好好學習吧")
case age > 25 && age < 35:
fmt.Println("好好工作吧")
case age > 60:
fmt.Println("好好享受吧")
default:
fmt.Println("活着真好")
}
}
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
5.goto(跳轉到指定標籤)
描述: goto
語句通過標籤進行代碼間的無條件跳轉。goto
語句可以在快速跳出循環、避免重複退出上有一定的幫助, Go 語言中使用goto
語句能簡化一些代碼的實現過程。
例如: 雙層嵌套的 for 循環要退出時
func gotoDemo1() {
var breakFlag bool
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 設置退出標籤
breakFlag = true
break
}
fmt.Printf("%v-%v\n", i, j)
}
// 外層for循環判斷
if breakFlag {
break
}
}
}
使用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循環")
fmt.Println("已結束for循環")
}
執行結果:
0-0
0-1
正結束for循環
已結束for循環
6.break(跳出循環)
描述: break
語句可以結束for
、switch
和select
的代碼塊。
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("...")
}
7.continue(繼續下次循環)
描述: continue
語句可以結束當前循環,開始下一次的循環迭代過程,僅限在for
循環內使用。
在 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)
}
}
}
歡迎關注 “WeiyiGeek” 公衆號
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/MS_lSaA72Qk5nyJjDhY1mg