91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Golang基礎的示例分析

發布時間:2021-12-15 09:39:19 來源:億速云 閱讀:147 作者:小新 欄目:云計算

這篇文章將為大家詳細講解有關Golang基礎的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

第一個golang程序

package main

import "fmt"

func main() {
	fmt.Println("hello golang")
}

基本數據類型

  1. 布爾型( true 或者 false)

  2. 數字類型( 整型 int 和 浮點型 float32、float64 )

  3. 字符串類型( 字符串就是一串固定長度的字符連接起來的字符序列 )

  4. 派生類型:

  • 指針類型(Pointer)

  • 數組類型

  • 結構化類型(struct)

  • Channel 類型

  • 函數類型

  • 切片類型

  • 接口類型(interface)

  • Map 類型

數字類型

  1. 整形

  • 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)

  1. 浮點型

  • float32 32位浮點型數

  • float64 64位浮點型數

  • complex64 32 位實數和虛數

  • complex128 64 位實數和虛數

  1. 其他數字類型

  • 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,特殊常量,可以認為是一個可以被編譯器修改的常量

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

條件控制語句

if & if else

package main

import "fmt"

func main() {
	var a = 12
	if a > 10 {
		fmt.Println("a>10")
	} else {
		fmt.Println("a<=10")
	}
}

運行結果

a>10

switch

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

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

循環控制語句

for

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

切片(Slice)

Go 數組的長度不可改變,與數組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。

定義切片

  1. var identifier []type

  2. var slice1 []type = make([]type, len) 或者簡寫 slice1 := make([]type, len) 指定長度

  3. 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]

范圍(Range)

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 是一種無序的鍵值對的集合。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)

通道(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基礎的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盘山县| 咸丰县| 县级市| 五指山市| 台湾省| 玉龙| 阳泉市| 南郑县| 改则县| 英德市| 泰和县| 彰化县| 长沙市| 阜康市| 习水县| 泰州市| 聂荣县| 桐庐县| 来宾市| 怀仁县| 泉州市| 南澳县| 屏山县| 高阳县| 库伦旗| 连江县| 安丘市| 耒阳市| 黄石市| 集贤县| 永安市| 普洱| 天峻县| 南和县| 沿河| 安多县| 广东省| 巴林左旗| 嘉兴市| 顺义区| 囊谦县|