golang基础归纳
1. hello-world
package main import "fmt"func main(){ fmt.Println("Hello world, Go Go!"); fmt.Printf("type of Hello is %T\n", "Hello") }package main--每一個Go文件都應該在開頭進行package name的聲明(注:只有可執行程序的包名為main)。包用于代碼的封裝與重用,這里包名為main。位于第一行。
import "fmt"--導入fmt包,下面代碼要使用。
2. 注釋
單行注釋://
多行注釋:/* */
3. 空白符
_在Go中被用作空白符,可以表示任何類型的任何值。
4. 類型
布爾:bool??? // true,false
字符串:string
數字類型:int8,int16,int32,int64,int
uint8,uint16,uint32,uint64,uint
float32,float64
complex64,complex128
byte
rune
注:int,根據不同的底層平臺,表示32或64位整型。除非對整形的大小有特定的需求,否則通常應該使用int表示整型。
注:byte是uint8的別名,rune是int32的別名。
注:+操作符用于拼接字符串。
5. 類型轉換
Go有著非常嚴格的強類型特征,沒有自動類型提升或類型轉換,不允許將一種類型的變量賦值給另一種類型的變量。
若要類型轉換,需要顯式類型裝換,如int(f)等。
i := 60.5 j := 50 sum := i + float64(j)自聲明類型也不能和相同原類型混合使用:
var str string = "Hello"type myString stringvar customName myString = "world"customName = str // 不允許6. 格式說明符
%T:打印變量的類型
%v:打印變量的值
fmt.Printf("type of sum is %T\n", sum)7. sizeof
Go的unsafe包提供一個Sizeof函數,該函數接收變量并返回它的字節大小。unsafe包應該小心使用,因為使用unsafe包可能帶來可移植性問題。
8. 變量
var name type name = initalvalue var name type = initalvalue var name = initalvalue // 類型推斷 var name1, name2 type = initalvalue1, initalvalue2 var ( name1 = initalvalue1 name2 = initalvalue2 ) // 一條語句聲明不同類型變量 name := initalvalue // 簡短聲明用:=注:簡短聲明要求:=操作符左邊的所有變量都要有初始值;要求:=操作符的左邊至少有一個變量是尚未聲明的。
注意:go語言中定義的變量必須被用到,否則會報錯。
9. 常量
雙引號中的任何值都是Go中的字符串常量。
無類型的常量有一個與它們相關聯的默認類型,并且當且僅當一行代碼需要時才提供它。在聲明中?var name = "Sam"?,?name需要一個類型,它從字符串常量?Sam?的默認類型中獲取。
const a = 5 var intVar int = a var int32Var int32 = a var float64Var float64 = a var complex64Var complex64 = a fmt.Println("intVar", intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var", complex64Var)a?的值是?5?,a?的語法是通用的(它可以代表一個浮點數、整數甚至是一個沒有虛部的復數),因此可以將其分配給任何兼容的類型。這些常量的默認類型可以被認為是根據上下文在運行中生成的。?var intVar int = a?要求?a?是?int,所以它變成一個?int?常量。?var complex64Var complex64 = a?要求?a?是?complex64,因此它變成一個復數類型。
10. 函數
func functionname(parametername1 type, parametername1 type) returntype { // 函數體(具體實現的功能) }如果有連續若干個參數,它們的類型一致,那么我們無須一一羅列,只需在最后一個參數后添加該類型。
從函數中可以返回一個命名值。一旦命名了返回值,可以認為這些值在函數第一行就被聲明為變量了。
func rectProps(length, width float64)(area, perimeter float64) { area = length * widthperimeter = (length + width) * 2return // 不需要明確指定返回值,默認返回 area, perimeter 的值 }11. 包
包用于組織Go源代碼,提供了更好的可重用性和可讀性。
屬于某一個包的源文件都應該放置于一個單獨命名的文件夾里。按照 Go 的慣例,應該用包名命名該文件夾。
導出名字
在 Go 中,任何以大寫字母開頭的變量或者函數都是被導出的名字。其它包只能訪問被導出的函數和變量。
同一個包中,所有變量和函數都可調用,無論首字母是否大小寫。
init函數
所有包都可以包含一個?init?函數。init 函數不應該有任何返回值類型和參數,在我們的代碼中也不能顯式地調用它。init 函數的形式如下:
func init() { }init 函數可用于執行初始化任務,也可用于在開始執行之前驗證程序的正確性。
包的初始化順序
首先初始化包級別(Package Level)的變量
緊接著調用 init 函數。包可以有多個 init 函數(在一個文件或分布于多個文件中),它們按照編譯器解析它們的順序進行調用。
如果一個包導入了另一個包,會先初始化被導入的包。盡管一個包可能會被導入多次,但是它只會被初始化一次。
空白標識符
導入了包,卻不在代碼中使用它,這在 Go 中是非法的。有兩種處理方法:
1)錯誤屏蔽器。在導入包后,用空白符引用包的變量。var _ = rectangle.Area
2)導入包語句前使用空白符。_"geometry/rectangle"
12. 條件判斷
if condition { } else if condition { } else { }或
if statement; condition { }注:else?語句應該在?if?語句的大括號?}?之后的同一行中。如果不是,編譯器會不通過。
13. 循環
for是Go語言中唯一的循環語句。Go中沒有while和do while循環。
for initialisation; condition; post { }其中initialization和post可以省略,而只使用condition
for i <= 10 { //semicolons are ommitted and only condition is presentfmt.Printf("%d ", i)i += 2 }若condition也省略則表示無限循環。
14. switch
基礎用法和C語言相似,包含switch…case…case…default。
通過用逗號分隔,可以在一個 case 中包含多個表達式。 case 1,2, 3, 4, 5:
switch中表達式可省略。如果省略表達式,則表示這個 switch 語句等同于?switch true,并且每個?case?表達式都被認定為有效,相應的代碼塊也會被執行。
num := 75switch { // 表達式被省略了case num >= 0 && num <= 50:fmt.Println("num is greater than 0 and less than 50")case num >= 51 && num <= 100:fmt.Println("num is greater than 51 and less than 100")case num >= 101:fmt.Println("num is greater than 100")}在 Go 中,每執行完一個 case 后,會從 switch 語句中跳出來,不再做后續 case 的判斷和執行。使用?fallthrough?語句可以在已經執行完成的 case 之后,把控制權轉移到下一個 case 的執行代碼中。
switch num := number(); { // num is not a constantcase num < 50:fmt.Printf("%d is lesser than 50\n", num)fallthroughcase num < 100:fmt.Printf("%d is lesser than 100\n", num)fallthroughcase num < 200:fmt.Printf("%d is lesser than 200", num)}fallthrough?語句應該是 case 子句的最后一個語句。如果它出現在了 case 語句的中間,編譯器將會報錯:fallthrough statement out of place
15. 數組
Go語言不允許混合不同類型的元素。
[n]T,n表示數組中元素的數量,T代表每個元素的類型。
var a [3]int聲明了一個長度為3的整型數組。數組中的所有元素都被自動賦值為數組類型的零值。
數組的索引從0開始到length-1結束,長度用函數len()計算。
a := [3]int{10, 11, 12} //簡略聲明
a := [3]int{10}
a := […]int{10, 11, 12} //忽略數組長度,用…代替
數組的大小是類型的一部分,因此[5]int和[20]int是不同類型。
Go中的數組是值類型而不是引用類型。這意味著當數組賦值給一個新的變量時,該變量會得到一個原始數組的一個副本。對新變量的更改,不會影響原始數組。
for i, v := range arr {} // range方法遍歷數組
for _, v := range arr {} //忽略索引
a := [3][2]string{{"lion", "tiger"},{"cat", "dog"},{"pigeon", "peacock"}, // this comma is necessary. The compiler will complain if you omit this comma}多維數組最后一組末尾要加逗號,否則根據Go語言的規則會自動插入分號。
16. 切片
切片是由數組簡歷的一種方便、靈活且功能強大的包裝(wrapper)。切片本身不擁有任何數據,只是對現有數組的引用。對切片的所有修改都會反映到底層數組上。
切片用[]T表示。
a[start:end]創建一個從a數組索引start開始到end-1結束的切片。
numa := [3]int{78, 79 ,80} nums1 := numa[:] // creates a slice which contains all elements of the arraynuma[:]缺少開始和結束值,開始和結束默認值分別是0和len(numa)。
切片的長度是切片中的元素數。切片的容量是從創建切片索引開始的底層數組中元素數。
func make([]T,len,cap)[]T 通過傳遞類型,長度和容量來創建切片。容量是可選參數, 默認值為切片長度。make 函數創建一個數組,并返回引用該數組的切片。
func append(s[]T,x ... T)[]T用于向切片追加元素。
如果切片由數組支持,并且數組本身的長度是固定的,那么切片如何具有動態長度,以及內部發生了什么?當新的元素被添加到切片時,會創建一個新的數組。現有數組的元素被復制到這個新數組中,并返回這個新數組的新切片引用。現在新切片的容量是舊切片的兩倍。
切片類型的零值為?nil。一個?nil?切片的長度和容量為 0。
veggies := []string{"potatoes", "tomatoes", "brinjal"}fruits := []string{"oranges", "apples"}food := append(veggies, fruits...)可以使用?...?運算符將一個切片添加到另一個切片。
值傳遞
切片在內部可看作由一個結構體類型表示:
type slice struct { Length intCapacity intZerothElement *byte }切片包含長度、容量和指向數組第零個元素的指針。當切片傳遞給函數時,即使它通過值傳遞,指針變量也將引用相同的底層數組。因此,當切片作為參數傳遞給函數時,函數內所做的更改也會在函數外可見。
內存優化
切片持有對底層數組的引用。只要切片在內存中,數組就不能被垃圾回收。這里需要重點注意的是,在切片引用時數組仍然存在內存中。
一種解決方法是使用?copy?函數?func copy(dst,src[]T)int?來生成一個切片的副本。這樣我們可以使用新的切片,原始數組可以被垃圾回收。
17. 可變參數的函數
如果函數最后一個參數被記作?...T?,這時函數可以接受任意個?T?類型參數作為最后一個參數。請注意只有函數的最后一個參數才允許是可變的。
可變參數函數的工作原理是把可變參數轉換為一個新的切片。?
func find(num int, nums ...int) {for i, v := range nums {if v == num {fmt.Println(num, "found at index", i, "in", nums)}} } find(30, 10, 20, 30, 40)find(30)也是合法的,此時?nums?是一個長度和容量為 0 的?nil?切片。
有一個可以直接將切片傳入可變參數函數的語法糖,你可以在在切片后加上?...?后綴。如果這樣做,切片將直接傳入函數,不再創建新的切片。
find(89, nums…) // true一個易錯例程:?
package mainimport ("fmt" )func change(s ...string) {s[0] = "Go"s = append(s, "playground")fmt.Println(s) }func main() {welcome := []string{"hello", "world"}change(welcome...)fmt.Println(welcome) } output: [Go world playground] [Go world]18. 鍵值對map
map將鍵值關聯的內置類型,通過相應的鍵可以獲取到值。
make(map[type of key]type of value):創建map。
map 的零值是?nil。如果你想添加元素到 nil map 中,會觸發運行時 panic。因此 map 必須使用?make?函數初始化。
鍵不一定只能是 string 類型。所有可比較的類型,如 boolean,interger,float,complex,string 等,都可以作為鍵。關于可比較的類型,如果你想了解更多,請訪問?http://golang.org/ref/spec#Comparison_operators。
獲取map中元素
訪問map中不存在的元素,map會返回該元素類型的零值。
可通過如下語法判斷key是否存在,如果ok是true,表示key存在,key對應的值就是value,反之key不存在。?
value, ok := map[key]for range遍歷map
personSalary := map[string]int{"steve": 12000,"jamie": 15000,}personSalary["mike"] = 9000for key, value := range personSalary {fmt.Printf("personSalary[%s] = %d\n", key, value)}注意,當使用?for range?遍歷 map 時,不保證每次執行程序獲取的元素順序相同。
delete(map, key):刪除?map?中?key?,這個函數沒有返回值。
len(man):獲取map長度。
Map是引用類型,當 map 被賦值為一個新變量的時候,它們指向同一個內部數據結構。因此,改變其中一個變量,就會影響到另一變量。
map 之間不能使用?==?操作符判斷,==?只能用來檢查 map 是否為?nil。判斷兩個 map 是否相等的方法是遍歷比較兩個 map 中的每個元素。map類型是不可比較的。
19. 字符串
字符串就是一個字節切片。Go 中的字符串是兼容 Unicode 編碼的,并且使用 UTF-8 進行編碼。
len(s)返回字符串中字節的數量。
在 UTF-8 編碼中,一個代碼點可能會占用超過一個字節的空間。需要使用rune。
rune 是 Go 語言的內建類型,它也是 int32 的別稱。在 Go 語言中,rune 表示一個代碼點。代碼點無論占用多少個字節,都可以用一個 rune 來表示。
func printChars(s string) {runes := []rune(s)for i:= 0; i < len(runes); i++ {fmt.Printf("%c ",runes[i])} } // rune切片構造字符串 runeSlice := []rune{0x0053, 0x0065, 0x00f1, 0x006f, 0x0072}func RuneCountInString(s string) (n int):獲取字符串長度,需導入包unicode/utf8。
字符串是不可變得。為了修改字符串,可以把字符串轉化為一個 rune 切片。然后這個切片可以進行任何想要的改變,然后再轉化為一個字符串。?
func mutate(s []rune) string { s[0] = 'a' return string(s) } fmt.Println(mutate([]rune(h)))20. 指針
*T指向一個T類型的變量。
指針的零值時nil。?
var a int = 25 var b *int = &a*b++ fmt.Printf("Type of b is %T\n", b) fmt.Println("b is", b) output: Type of b is *int b is 0xc420072010 a is 26?不要向函數傳遞數組的指針,而應該使用切片。
對于數組:(*arr)[x]與arr[x]等價,arr是數組指針。
var arr *[3]int = [3]int{90, 100, 110}
Go 并不支持其他語言(例如 C)中的指針運算,如b++,但支持*b++。
21. 結構體
type Employee struct {firstName, lastName stringage, salary int }Employee被稱為命名結構體。
當定義好的結構體并沒有被顯式地初始化時,該結構體的字段將默認賦為零值。僅為某些字段指定初始值時,忽略的字段會賦值為零值。
對于結構體指針,?emp8.firstName?與?(*emp8).firstName等價。
匿名字段的名稱就默認為它的類型。?
type Person struct { stringint }var p1 Personp1.string = "naveen"p1.int = 50fmt.Println(p1)提升字段(Promoted Fields)
如果是結構體中有匿名的結構體類型字段,則該匿名結構體里的字段就稱為提升字段。這是因為提升字段就像是屬于外部結構體一樣,可以用外部結構體直接訪問。
type Address struct {city, state string } type Person struct {name stringage intAddress }var p Personp.name = "Naveen"p.age = 50p.Address = Address{city: "Chicago",state: "Illinois",}fmt.Println("Name:", p.name)fmt.Println("Age:", p.age)fmt.Println("City:", p.city) //city is promoted fieldfmt.Println("State:", p.state) //state is promoted field導出結構體和字段
如果結構體名稱以大寫字母開頭,則它是其他包可以訪問的導出類型(Exported Type)。同樣,如果結構體里的字段首字母大寫,它也能被其他包訪問到。
結構體相等性(Structs Equality)
結構體是值類型。如果它的每一個字段都是可比較的,則該結構體也是可比較的。如果兩個結構體變量的對應字段相等,則這兩個變量也是相等的。如果結構體包含不可比較的字段,則結構體變量也不可比較。
type name struct { firstName stringlastName string }name1 := name{"Steve", "Jobs"}name2 := name{"Steve", "Jobs"}if name1 == name2 {fmt.Println("name1 and name2 are equal")}?22. defer
含有defer語句的函數,會在該函數將要返回之前,調用另一個函數。
在 Go 語言中,并非在調用延遲函數的時候才確定實參,而是當執行?defer?語句的時候,就會對延遲函數的實參進行求值。
package main import ("fmt""time" )func finished(v int){fmt.Printf("Finished something:%d\n", v) }func process(v int){defer finished(v)fmt.Printf("Start processing...%d\n", v)time.Sleep(2*time.Second)v = 3fmt.Printf("End processing...%d\n", v) }func main(){process(5) } output: Start processing...5 End processing...3 Finished something:5當一個函數內多次調用?defer?時,Go 會把?defer?調用放入到一個棧中,隨后按照后進先出(Last In First Out, LIFO)的順序執行。
23.?時間
time包提供時間相關處理函數。
now := time.Now()? time.Now().Day() time.Now().Minute() time.Now().Month()
func Now() Time func (t Time) Nanosecond() int func (t Time) Second() int func (t Time) Minute() int func (t Time) Day() int func (t Time) Month() Month func (t Time) String() string const (Nanosecond Duration = 1Microsecond = 1000 * NanosecondMillisecond = 1000 * MicrosecondSecond = 1000 * MillisecondMinute = 60 * SecondHour = 60 * Minute )A Duration represents the elapsed time between two instants as an int64 nanosecond count.?
type Duration int6424. strings和strconv
strings
strings.HasPrefix(s string, preffix string) bool:
判斷字符串s是否以prefix開頭
stirngs.HasSuffix(s string, suffix string) bool:
判斷字符串s是否以suffix結尾
strings.Index(s string, str string) int:
判斷str在s中首次出現的位置,如果沒有出現,則返回-1
strings.LastIndex(s string,str string) int:
判斷str在s中最后出現的位置,如果沒有出現,則返回-1
strings.Replace(str string,old string,new string,n int):
字符串替換
strings.Count(str string,count int)string:
字符串計數
strings.Repeat(str string,count int) string:
重復count次str
strings.ToLower(str string)
轉換為小寫
strings.ToUpper(str string)string:
轉換為大寫
strings.TrimSpace(str string):
去掉字符串首位空白字符
strings.Trim(str string,cut string):
去掉字符串首尾cut字符
strings.TrimLeft(str string,cut string):
去掉字符串首部cut字符
strings.TrimRight(str string,cunt string):
去掉字符串尾部cut字符
strings.Field(str string):
返回str空格分隔的所有子串的slice
string.Split(str string,split string):
返回str split分割的所有子串的slice
strings.Join(s1 []string,sep string):
用sep把s1中的所有元素連接起來
strconv
strconv.Itoa(i int):把一個整數轉換成字符串
strconv.Atoi (str string)(int,errror): 把一個字符串轉換成整數
25. 終端操作
os.Stdin:標準輸入
os.Stdout:標準輸出
os.Stderr:標準錯誤輸出
?
參考:
1.?How to write Go Code??https://golang.google.cn/doc/code.html
2.?https://golang.google.cn/?提供go在線測試環境和文檔
3.?https://golang.google.cn/doc/?go相關文檔
4.?https://golang.google.cn/pkg/?go標準庫
5.? ?https://godoc.org/?go實用庫搜索
6.?go基礎學習 coder python修行路
7. Go 系列教程(Golang tutorial series) go語言中文網
8.??go基礎學習 coder python修行路
轉載于:https://www.cnblogs.com/embedded-linux/p/11025159.html
總結
以上是生活随笔為你收集整理的golang基础归纳的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Microsoft Edge Chrom
- 下一篇: python课堂整理9---函数1