您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Golang基礎的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
package main import "fmt" func main() { fmt.Println("hello golang") }
布爾型( true 或者 false)
數字類型( 整型 int 和 浮點型 float32、float64 )
字符串類型( 字符串就是一串固定長度的字符連接起來的字符序列 )
派生類型:
指針類型(Pointer)
數組類型
結構化類型(struct)
Channel 類型
函數類型
切片類型
接口類型(interface)
Map 類型
整形
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)
浮點型
float32 32位浮點型數
float64 64位浮點型數
complex64 32 位實數和虛數
complex128 64 位實數和虛數
其他數字類型
byte 類似 uint8
rune 類似 int32
uint 32 或 64 位
int 與 uint 一樣大小
uintptr 無符號整型,用于存放一個指針
// 聲明一個變量 var identifier type // 可以一次聲明多個變量 var identifier1, identifier2 type // 根據值自行判定變量類型 var v_name = value // 簡短形式 省略 var, 注意 := 左側如果沒有聲明新的變量 v_name := value
// 聲明一個常量 const identifier [type] = value // 顯式類型定義 const b string = "abc" // 隱式類型定義 const b = "abc" // 多個相同類型的聲明(隱式類型定義) const c_name1, c_name2 = value1, value2
iota,特殊常量,可以認為是一個可以被編譯器修改的常量
iota 在 const關鍵字出現時將被重置為 0(const 內部的第一行之前),const 中每新增一行常量聲明將使 iota 計數一次(iota 可理解為 const 語句塊中的行索引)。
iota 可以被用作枚舉值
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //獨立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢復計數 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
運行結果
0 1 2 ha ha 100 100 7 8
第一個 iota 等于 0,每當 iota 在新的一行被使用時,它的值都會自動加 1
package main import "fmt" func main() { var a = 12 if a > 10 { fmt.Println("a>10") } else { fmt.Println("a<=10") } }
運行結果
a>10
package main import "fmt" func main() { var a = 12 switch a { case 1: fmt.Println(1) case 2: fmt.Println(2) case 12: fmt.Println(12) default: fmt.Println(a) } }
運行結果
12
使用 fallthrough 會強制執行后面的 case 語句,fallthrough 不會判斷下一條 case 的表達式結果是否為 true
package main import "fmt" func main() { var a = 1 switch a { case 1: fmt.Println(1) fallthrough case 2: fmt.Println(2) case 12: fmt.Println(12) default: fmt.Println(a) } }
運行結果
1 2
select 是 Go 中的一個控制結構,類似于用于通信的 switch 語句。每個 case 必須是一個通信操作,要么是發送要么是接收。
select 隨機執行一個可運行的 case。如果沒有 case 可運行,它將阻塞,直到有 case 可運行。一個默認的子句應該總是可運行的。
package main import "fmt" func main() { var c1, c2, c3 chan int var i1, i2 int select { case i1 = <-c1: fmt.Printf("received ", i1, " from c1\n") case c2 <- i2: fmt.Printf("sent ", i2, " to c2\n") case i3, ok := <-c3: if ok { fmt.Printf("received ", i3, " from c3\n") } else { fmt.Printf("c3 is closed\n") } default: fmt.Printf("no communication\n") } }
運行結果
no communication
package main import "fmt" func main() { for i := 1; i < 10; i++ { fmt.Println(i) } }
package main import "fmt" func main() { var i = 1 for i < 10 { fmt.Println(i) i++ } }
運行結果
1 2 3 4 5 6 7 8 9
死循環
for { }
package main import "fmt" func main() { test(1) } func test(i int) int { for i < 10 { fmt.Println(i) i++ } return i }
運行結果
1 2 3 4 5 6 7 8 9
package main import "fmt" func main() { i := test(1, 9) fmt.Println("最大值為:", i) } func test(i, j int) int { if i > j { return i } else { return j } }
運行結果
最大值為: 9
package main import "fmt" func main() { s, s2 := test("hello", "go") fmt.Println(s, s2) } func test(i, j string) (string, string) { return i, j }
運行結果
hello go
package main import "fmt" func main() { var a = 3 var b = 4 fmt.Println("值傳遞運行前a=", a, "b=", b) test1(a, b) fmt.Println("值傳遞運行后a=", a, "b=", b) fmt.Println("===============================================") var i = 1 var j = 2 fmt.Println("引用傳遞運行前i=", i, "j=", j) test2(&i, &j) fmt.Println("引用傳遞運行后i=", i, "j=", j) } // 值傳遞 func test1(i, j int) (int, int) { var temp int temp = i i = j j = temp return i, j } // 引用傳遞 func test2(i, j *int) (int, int) { var temp int temp = *i *i = *j *j = temp return *i, *j }
運行結果
值傳遞運行前a= 3 b= 4 值傳遞運行后a= 3 b= 4 =============================================== 引用傳遞運行前i= 1 j= 2 引用傳遞運行后i= 2 j= 1
package main import "fmt" func main() { funcA := func(a int) int { return a } fmt.Println(funcA(12)) }
運行結果
12
Go 語言支持匿名函數,可作為閉包。匿名函數是一個"內聯"語句或表達式。匿名函數的優越性在于可以直接使用函數內的變量,不必申明。
package main import "fmt" func main() { next := getSequence() fmt.Println(next()) fmt.Println(next()) fmt.Println(next()) } func getSequence() func() int { a := 1 return func() int { a++ return a } }
運行結果
2 3 4
Go 語言中同時有函數和方法。一個方法就是一個包含了接受者的函數,接受者可以是命名類型或者結構體類型的一個值或者是一個指針。所有給定類型的方法屬于該類型的方法集
package main import "fmt" type Circle struct { radius float64 } func (circle Circle) getPerimeter() float64 { return 3.14 * circle.radius * 2 } func main() { var circle Circle circle.radius = 10 fmt.Println(circle.getPerimeter()) }
運行結果
62.800000000000004
Go 語言中變量可以在三個地方聲明:
函數內定義的變量稱為局部變量
函數外定義的變量稱為全局變量
函數定義中的變量稱為形式參數
package main import "fmt" // 全局變量 var a = 1 func main() { // 局部變量 var b = 2 test(a) test(b) } // 形式參數 func test(a int) { fmt.Println(a) }
數組是具有相同唯一類型的一組已編號且長度固定的數據項序列,這種類型可以是任意的原始類型例如整形、字符串或者自定義類型
// 形式 var variable_name [SIZE] variable_type // 舉例 var balance [10] float32
// 初始化一個長度為5的float32數組 var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} // 如果忽略 [] 中的數字不設置數組大小 var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} balance[6] = 60.0
var a float32 = balance[5]
一個指針變量指向了一個值的內存地址
// 形式 var var_name *var-type // 舉例 var ip *int /* 指向整型*/ var fp *float32 /* 指向浮點型 */
package main import "fmt" func main() { var a int = 20 /* 聲明實際變量 */ var ip *int /* 聲明指針變量 */ ip = &a /* 指針變量的存儲地址 */ fmt.Printf("a 變量的地址是: %x\n", &a) /* 指針變量的存儲地址 */ fmt.Printf("ip 變量儲存的指針地址: %x\n", ip) /* 使用指針訪問值 */ fmt.Printf("*ip 變量的值: %d\n", *ip) }
運行結果
a 變量的地址是: c00000a0b0 ip 變量儲存的指針地址: c00000a0b0 *ip 變量的值: 20
當一個指針被定義后沒有分配到任何變量時,它的值為 nil。
nil 指針也稱為空指針。一個指針變量通常縮寫為 ptr。
package main import "fmt" func main() { var ip *int /* 聲明指針變量 */ /* 指針變量的存儲地址 */ fmt.Printf("ip 的值為: %x\n", ip) }
運行結果
ip 的值為: 0
if(ptr != nil) /* ptr 不是空指針 */ if(ptr == nil) /* ptr 是空指針 */
package main import "fmt" func main() { a := []int{10, 100, 200} // 遍歷數組 for i := 0; i < len(a); i++ { fmt.Printf("a[%d] = %d\n", i, a[i]) } fmt.Println("==================================") // 有一種情況,我們可能需要保存數組,這樣我們就需要使用到指針。 // 以下聲明了整型指針數組: var ptr [3]*int for i := 0; i < len(a); i++ { /* 整數地址賦值給指針數組 */ ptr[i] = &a[i] } for i := 0; i < len(ptr); i++ { fmt.Printf("a[%d] = %d\n", i, *ptr[i]) } }
運行結果
a[0] = 10 a[1] = 100 a[2] = 200 ================================== a[0] = 10 a[1] = 100 a[2] = 200
如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量為指向指針的指針變量。 指向指針的指針變量聲明格式
var ptr **int;
package main import "fmt" func main() { var a int var ptr *int var pptr **int a = 3000 /* 指針 ptr 地址 */ ptr = &a /* 指向指針 ptr 地址 */ pptr = &ptr /* 獲取 pptr 的值 */ fmt.Printf("變量 a = %d\n", a) fmt.Printf("指針變量 *ptr = %d\n", *ptr) fmt.Printf("指向指針的指針變量 **pptr = %d\n", **pptr) }
運行結果
變量 a = 3000 指針變量 *ptr = 3000 指向指針的指針變量 **pptr = 3000
package main import "fmt" func main() { var a = 3 var b = 4 fmt.Println("值傳遞運行前a=", a, "b=", b) test1(a, b) fmt.Println("值傳遞運行后a=", a, "b=", b) fmt.Println("===============================================") var i = 1 var j = 2 fmt.Println("引用傳遞運行前i=", i, "j=", j) test2(&i, &j) fmt.Println("引用傳遞運行后i=", i, "j=", j) } // 值傳遞 func test1(i, j int) (int, int) { var temp int temp = i i = j j = temp return i, j } // 引用傳遞 func test2(i, j *int) (int, int) { var temp int temp = *i *i = *j *j = temp return *i, *j }
運行結果
值傳遞運行前a= 3 b= 4 值傳遞運行后a= 3 b= 4 =============================================== 引用傳遞運行前i= 1 j= 2 引用傳遞運行后i= 2 j= 1
結構體是由一系列具有相同類型或不同類型的數據構成的數據集合。
結構體表示一項記錄,比如保存圖書館的書籍記錄,每本書有以下屬性:
Title :標題 Author : 作者 Subject:學科 ID:書籍ID
type struct_variable_type struct { member definition member definition ... member definition }
一旦定義了結構體類型,它就能用于變量的聲明,語法格式如下:
variable_name := structure_variable_type {value1, value2...valuen} 或 variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
package main import "fmt" // 一、定義結構體 type Books struct { title string author string subject string book_id int } func main() { // 創建一個新的結構體 fmt.Println(Books{"Go 語言", "Google", "Go 語言教程", 6495407}) // 也可以使用 key => value 格式 fmt.Println(Books{title: "Go 語言", author: "Google", subject: "Go 語言教程", book_id: 6495407}) // 忽略的字段為 0 或 空 fmt.Println(Books{title: "Go 語言", author: "Google"}) fmt.Println("=========================") // 二、訪問結構體成員 /* book 2 描述 */ var Book2 Books Book2.title = "Python 教程" Book2.author = "Python" Book2.subject = "Python 語言教程" Book2.book_id = 6495700 /* 打印 Book2 信息 */ fmt.Printf("Book 2 title : %s\n", Book2.title) fmt.Printf("Book 2 author : %s\n", Book2.author) fmt.Printf("Book 2 subject : %s\n", Book2.subject) fmt.Printf("Book 2 book_id : %d\n", Book2.book_id) fmt.Println("=========================") // 三、結構體作為函數參數 printBook(Book2) fmt.Println("=========================") // 四、結構體指針 printBook2(&Book2) } func printBook(book Books) { fmt.Printf("Book title : %s\n", book.title) fmt.Printf("Book author : %s\n", book.author) fmt.Printf("Book subject : %s\n", book.subject) fmt.Printf("Book book_id : %d\n", book.book_id) } func printBook2(book *Books) { fmt.Printf("Book title : %s\n", book.title) fmt.Printf("Book author : %s\n", book.author) fmt.Printf("Book subject : %s\n", book.subject) fmt.Printf("Book book_id : %d\n", book.book_id) }
運行結果
{Go 語言 Google Go 語言教程 6495407} {Go 語言 Google Go 語言教程 6495407} {Go 語言 Google 0} ========================= Book 2 title : Python 教程 Book 2 author : Python Book 2 subject : Python 語言教程 Book 2 book_id : 6495700 ========================= Book title : Python 教程 Book author : Python Book subject : Python 語言教程 Book book_id : 6495700 ========================= Book title : Python 教程 Book author : Python Book subject : Python 語言教程 Book book_id : 6495700
Go 數組的長度不可改變,與數組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。
var identifier []type
var slice1 []type = make([]type, len) 或者簡寫 slice1 := make([]type, len) 指定長度
make([]T, length, capacity) 指定容量
package main import "fmt" func main() { // 切片初始化 var slice = []int{1, 2, 3} // 從下標startIndex到endIndex-1 下的元素 切片截取 fmt.Println(slice[0:2]) fmt.Println(slice[:2]) fmt.Println(slice[0:]) fmt.Println("=======================") // len() 和 cap() 函數 fmt.Printf("len=%d cap=%d slice=%v\n", len(slice), cap(slice), slice) fmt.Println("=======================") // 空切片 var numbers []int fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers), cap(numbers), numbers) if numbers == nil { fmt.Printf("切片是空的\n") } fmt.Println("=======================") // append() 和 copy() 函數 var numbers1 []int // append() 追加 numbers1 = append(numbers1, 1) numbers1 = append(numbers1, 2, 3, 4) fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers1), cap(numbers1), numbers1) fmt.Println("=======================") // copy() 復制 /* 創建切片 numbers2 是之前切片的兩倍容量*/ numbers2 := make([]int, len(numbers1), (cap(numbers1))*2) /* 拷貝 numbers1 的內容到 numbers2 */ copy(numbers2, numbers1) fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers2), cap(numbers2), numbers2) }
運行結果
[1 2] [1 2] [1 2 3] ======================= len=3 cap=3 slice=[1 2 3] ======================= len=0 cap=0 slice=[] 切片是空的 ======================= len=4 cap=4 slice=[1 2 3 4] ======================= len=4 cap=8 slice=[1 2 3 4]
package main import "fmt" func main() { //這是我們使用range去求一個slice的和。使用數組跟這個很類似 nums := []int{2, 3, 4} sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:", sum) //在數組上使用range將傳入index和值兩個變量。上面那個例子我們不需要使用該元素的序號,所以我們使用空白符"_"省略了。有時侯我們確實需要知道它的索引。 for i, num := range nums { if num == 3 { fmt.Println("index:", i) } } //range也可以用在map的鍵值對上。 kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s -> %s\n", k, v) } //range也可以用來枚舉Unicode字符串。第一個參數是字符的索引,第二個是字符(Unicode的值)本身。 for i, c := range "go" { fmt.Println(i, c) } }
運行結果
sum: 9 index: 1 a -> apple b -> banana 0 103 1 111
Map 是一種無序的鍵值對的集合。Map 最重要的一點是通過 key 來快速檢索數據,key 類似于索引,指向數據的值。
/* 聲明變量,默認 map 是 nil */ var map_variable map[key_data_type]value_data_type /* 使用 make 函數 */ map_variable := make(map[key_data_type]value_data_type)
如果不初始化 map,那么就會創建一個 nil map。nil map 不能用來存放鍵值對
package main import "fmt" func main() { var countryCapitalMap = make(map[string]string) /* map插入key - value對,各個國家對應的首都 */ countryCapitalMap["France"] = "巴黎" countryCapitalMap["Italy"] = "羅馬" countryCapitalMap["Japan"] = "東京" countryCapitalMap["India "] = "新德里" /*使用鍵輸出地圖值 */ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap[country]) } /*查看元素在集合中是否存在 */ capital, ok := countryCapitalMap["American"] /*如果確定是真實的,則存在,否則不存在 */ /*fmt.Println(capital) */ /*fmt.Println(ok) */ if ok { fmt.Println("American 的首都是", capital) } else { fmt.Println("American 的首都不存在") } fmt.Println("========================") // delete() 函數 for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap[country]) } // 刪除元素 delete(countryCapitalMap, "France") fmt.Println("法國條目被刪除") for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap[country]) } }
運行結果
France 首都是 巴黎 Italy 首都是 羅馬 Japan 首都是 東京 India 首都是 新德里 American 的首都不存在 ======================== India 首都是 新德里 France 首都是 巴黎 Italy 首都是 羅馬 Japan 首都是 東京 法國條目被刪除 Japan 首都是 東京 India 首都是 新德里 Italy 首都是 羅馬
遞歸,就是在運行的過程中調用自己
package main import "fmt" func main() { var i int = 15 fmt.Printf("%d 的階乘是 %d\n", i, Factorial(uint64(i))) } func Factorial(n uint64) (result uint64) { if n > 0 { result = n * Factorial(n-1) return result } return 1 }
運行結果
15 的階乘是 1307674368000
package main import "fmt" func main() { var i int for i = 0; i < 10; i++ { fmt.Printf("%d\t", fibonacci(i)) } } func fibonacci(n int) int { if n < 2 { return n } return fibonacci(n-2) + fibonacci(n-1) }
運行結果
0 1 1 2 3 5 8 13 21 34
類型轉換用于將一種數據類型的變量轉換為另外一種類型的變量。
type_name(expression)
package main import "fmt" func main() { var sum int = 17 var count int = 5 var mean float32 mean = float32(sum) / float32(count) fmt.Printf("mean 的值為: %f\n", mean) }
運行結果
mean 的值為: 3.400000
package main import "fmt" type Phone interface { call() } type NokiaPhone struct { } type IPhone struct { } func main() { n := new(NokiaPhone) n.call() i := new(IPhone) i.call() } func (NokiaPhone) call() { fmt.Println("nokiaPhone") } func (IPhone) call() { fmt.Println("IPhone") }
運行結果
nokiaPhone IPhone
Go 語言通過內置的錯誤接口提供了非常簡單的錯誤處理機制。
error類型是一個接口類型,這是它的定義
type error interface { Error() string }
我們可以在編碼中通過實現 error 接口類型來生成錯誤信息。
函數通常在最后的返回值中返回錯誤信息。使用errors.New 可返回一個錯誤信息
package main import ( "errors" "fmt" ) func main() { _, err := Sqrt(-1) if err != nil { fmt.Println(err) } } func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("math: square root of negative number") } // 實現 return f, nil }
運行結果
math: square root of negative number
Go 語言支持并發,我們只需要通過 go 關鍵字來開啟 goroutine 即可。
goroutine 是輕量級線程,goroutine 的調度是由 Golang 運行時進行管理的。
goroutine 語法格式:
go 函數名( 參數列表 )
Go 允許使用 go 語句開啟一個新的運行期線程, 即 goroutine,以一個不同的、新創建的 goroutine 來執行一個函數。 同一個程序中的所有 goroutine 共享同一個地址空間。
package main import ( "fmt" "time" ) func main() { go say("world") say("hello") } func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } }
運行結果
hello world world hello hello world world hello hello
通道(channel)是用來傳遞數據的一個數據結構。
通道可用于兩個 goroutine 之間通過傳遞一個指定類型的值來同步運行和通訊。操作符 <- 用于指定通道的方向,發送或接收。如果未指定方向,則為雙向通道。 聲明一個通道,通道在使用前必須先創建:
ch := make(chan int)
注意:默認情況下,通道是不帶緩沖區的。發送端發送數據,同時必須有接收端相應的接收數據。
package main import ( "fmt" ) func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // 從通道 c 中接收 fmt.Println(x, y, x+y) } func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // 把 sum 發送到通道 c }
運行結果
-5 17 12
通道可以設置緩沖區,通過 make 的第二個參數指定緩沖區大小:
ch := make(chan int, 100)
帶緩沖區的通道允許發送端的數據發送和接收端的數據獲取處于異步狀態,就是說發送端發送的數據可以放在緩沖區里面,可以等待接收端去獲取數據,而不是立刻需要接收端去獲取數據。
不過由于緩沖區的大小是有限的,所以還是必須有接收端來接收數據的,否則緩沖區一滿,數據發送端就無法再發送數據了。
注意:如果通道不帶緩沖,發送方會阻塞直到接收方從通道中接收了值。如果通道帶緩沖,發送方則會阻塞直到發送的值被拷貝到緩沖區內;如果緩沖區已滿,則意味著需要等待直到某個接收方獲取到一個值。接收方在有值可以接收之前會一直阻塞。
package main import ( "fmt" ) func main() { // 這里我們定義了一個可以存儲整數類型的帶緩沖通道 // 緩沖區大小為2 ch := make(chan int, 2) // 因為 ch 是帶緩沖的通道,我們可以同時發送兩個數據 // 而不用立刻需要去同步讀取數據 ch <- 1 ch <- 2 // 獲取這兩個數據 fmt.Println(<-ch) fmt.Println(<-ch) }
運行結果
1 2
Go 通過 range 關鍵字來實現遍歷讀取到的數據,類似于與數組或切片。格式如下:
v, ok := <-ch
package main import ( "fmt" ) func main() { c := make(chan int, 10) go fibonacci(cap(c), c) // range 函數遍歷每個從通道接收到的數據,因為 c 在發送完 10 個 // 數據之后就關閉了通道,所以這里我們 range 函數在接收到 10 個數據 // 之后就結束了。如果上面的 c 通道不關閉,那么 range 函數就不 // 會結束,從而在接收第 11 個數據的時候就阻塞了。 for i := range c { fmt.Println(i) } } func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } // 關閉通道 close(c) }
運行結果
0 1 1 2 3 5 8 13 21 34
關于“Golang基礎的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。