溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Golang基礎(chǔ)的示例分析

發(fā)布時(shí)間:2021-12-15 09:39:19 來(lái)源:億速云 閱讀:146 作者:小新 欄目:云計(jì)算

這篇文章將為大家詳細(xì)講解有關(guān)Golang基礎(chǔ)的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

第一個(gè)golang程序

package main

import "fmt"

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

基本數(shù)據(jù)類型

  1. 布爾型( true 或者 false)

  2. 數(shù)字類型( 整型 int 和 浮點(diǎn)型 float32、float64 )

  3. 字符串類型( 字符串就是一串固定長(zhǎng)度的字符連接起來(lái)的字符序列 )

  4. 派生類型:

  • 指針類型(Pointer)

  • 數(shù)組類型

  • 結(jié)構(gòu)化類型(struct)

  • Channel 類型

  • 函數(shù)類型

  • 切片類型

  • 接口類型(interface)

  • Map 類型

數(shù)字類型

  1. 整形

  • uint8 無(wú)符號(hào) 8 位整型 (0 到 255)

  • uint16 無(wú)符號(hào) 16 位整型 (0 到 65535)

  • uint32 無(wú)符號(hào) 32 位整型 (0 到 4294967295)

  • uint64 無(wú)符號(hào) 64 位整型 (0 到 18446744073709551615)

  • int8 有符號(hào) 8 位整型 (-128 到 127)

  • int16 有符號(hào) 16 位整型 (-32768 到 32767)

  • int32 有符號(hào) 32 位整型 (-2147483648 到 2147483647)

  • int64 有符號(hào) 64 位整型 (-9223372036854775808 到 9223372036854775807)

  1. 浮點(diǎn)型

  • float32 32位浮點(diǎn)型數(shù)

  • float64 64位浮點(diǎn)型數(shù)

  • complex64 32 位實(shí)數(shù)和虛數(shù)

  • complex128 64 位實(shí)數(shù)和虛數(shù)

  1. 其他數(shù)字類型

  • byte 類似 uint8

  • rune 類似 int32

  • uint 32 或 64 位

  • int 與 uint 一樣大小

  • uintptr 無(wú)符號(hào)整型,用于存放一個(gè)指針

定義變量

// 聲明一個(gè)變量
var identifier type
// 可以一次聲明多個(gè)變量
var identifier1, identifier2 type
// 根據(jù)值自行判定變量類型
var v_name = value
// 簡(jiǎn)短形式 省略 var, 注意 := 左側(cè)如果沒(méi)有聲明新的變量
v_name := value

定義常量

// 聲明一個(gè)常量
const identifier [type] = value
// 顯式類型定義
const b string = "abc"
// 隱式類型定義
const b = "abc"
// 多個(gè)相同類型的聲明(隱式類型定義)
const c_name1, c_name2 = value1, value2

iota

iota,特殊常量,可以認(rèn)為是一個(gè)可以被編譯器修改的常量

iota 在 const關(guān)鍵字出現(xiàn)時(shí)將被重置為 0(const 內(nèi)部的第一行之前),const 中每新增一行常量聲明將使 iota 計(jì)數(shù)一次(iota 可理解為 const 語(yǔ)句塊中的行索引)。

iota 可以被用作枚舉值

package main

import "fmt"

func main() {
	const (
		a = iota   //0
		b          //1
		c          //2
		d = "ha"   //獨(dú)立值,iota += 1
		e          //"ha"   iota += 1
		f = 100    //iota +=1
		g          //100  iota +=1
		h = iota   //7,恢復(fù)計(jì)數(shù)
		i          //8
	)
	fmt.Println(a,b,c,d,e,f,g,h,i)
}

運(yùn)行結(jié)果

0 1 2 ha ha 100 100 7 8

第一個(gè) iota 等于 0,每當(dāng) iota 在新的一行被使用時(shí),它的值都會(huì)自動(dòng)加 1

條件控制語(yǔ)句

if & if else

package main

import "fmt"

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

運(yùn)行結(jié)果

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

運(yùn)行結(jié)果

12

使用 fallthrough 會(huì)強(qiáng)制執(zhí)行后面的 case 語(yǔ)句,fallthrough 不會(huì)判斷下一條 case 的表達(dá)式結(jié)果是否為 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)
	}
}

運(yùn)行結(jié)果

1
2

select

select 是 Go 中的一個(gè)控制結(jié)構(gòu),類似于用于通信的 switch 語(yǔ)句。每個(gè) case 必須是一個(gè)通信操作,要么是發(fā)送要么是接收。

select 隨機(jī)執(zhí)行一個(gè)可運(yùn)行的 case。如果沒(méi)有 case 可運(yùn)行,它將阻塞,直到有 case 可運(yùn)行。一個(gè)默認(rèn)的子句應(yīng)該總是可運(yùn)行的。

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

運(yùn)行結(jié)果

no communication

循環(huán)控制語(yǔ)句

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

運(yùn)行結(jié)果

1
2
3
4
5
6
7
8
9

死循環(huán)

for {

}

函數(shù)

package main

import "fmt"

func main() {
	test(1)
}
func test(i int) int {
	for i < 10 {
		fmt.Println(i)
		i++
	}
	return i
}

運(yùn)行結(jié)果

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

運(yùn)行結(jié)果

最大值為: 9

函數(shù)返回多個(gè)值

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
}

運(yùn)行結(jié)果

hello go

值傳遞 和 引用傳遞

package main

import "fmt"

func main() {
	var a = 3
	var b = 4
	fmt.Println("值傳遞運(yùn)行前a=", a, "b=", b)
	test1(a, b)
	fmt.Println("值傳遞運(yùn)行后a=", a, "b=", b)
	fmt.Println("===============================================")
	var i = 1
	var j = 2
	fmt.Println("引用傳遞運(yùn)行前i=", i, "j=", j)
	test2(&i, &j)
	fmt.Println("引用傳遞運(yùn)行后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
}

運(yùn)行結(jié)果

值傳遞運(yùn)行前a= 3 b= 4
值傳遞運(yùn)行后a= 3 b= 4
===============================================
引用傳遞運(yùn)行前i= 1 j= 2
引用傳遞運(yùn)行后i= 2 j= 1

函數(shù)作為實(shí)參

package main

import "fmt"

func main() {
	funcA := func(a int) int {
		return a
	}
	fmt.Println(funcA(12))
}

運(yùn)行結(jié)果

12

閉包

Go 語(yǔ)言支持匿名函數(shù),可作為閉包。匿名函數(shù)是一個(gè)"內(nèi)聯(lián)"語(yǔ)句或表達(dá)式。匿名函數(shù)的優(yōu)越性在于可以直接使用函數(shù)內(nèi)的變量,不必申明。

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

運(yùn)行結(jié)果

2
3
4

方法

Go 語(yǔ)言中同時(shí)有函數(shù)和方法。一個(gè)方法就是一個(gè)包含了接受者的函數(shù),接受者可以是命名類型或者結(jié)構(gòu)體類型的一個(gè)值或者是一個(gè)指針。所有給定類型的方法屬于該類型的方法集

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

運(yùn)行結(jié)果

62.800000000000004

變量作用域

Go 語(yǔ)言中變量可以在三個(gè)地方聲明:

  • 函數(shù)內(nèi)定義的變量稱為局部變量

  • 函數(shù)外定義的變量稱為全局變量

  • 函數(shù)定義中的變量稱為形式參數(shù)

package main

import "fmt"

// 全局變量
var a = 1

func main() {
	// 局部變量
	var b = 2
	test(a)
	test(b)
}

// 形式參數(shù)
func test(a int) {
	fmt.Println(a)
}

數(shù)組

數(shù)組是具有相同唯一類型的一組已編號(hào)且長(zhǎng)度固定的數(shù)據(jù)項(xiàng)序列,這種類型可以是任意的原始類型例如整形、字符串或者自定義類型

聲明數(shù)組

// 形式
var variable_name [SIZE] variable_type
// 舉例
var balance [10] float32

初始化數(shù)組

// 初始化一個(gè)長(zhǎng)度為5的float32數(shù)組
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
// 如果忽略 [] 中的數(shù)字不設(shè)置數(shù)組大小
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
balance[6] = 60.0

訪問(wèn)數(shù)組元素

var a float32 = balance[5]

指針

一個(gè)指針變量指向了一個(gè)值的內(nèi)存地址

聲明指針

// 形式
var var_name *var-type
// 舉例
var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮點(diǎn)型 */
package main

import "fmt"

func main() {
	var a int = 20 /* 聲明實(shí)際變量 */
	var ip *int    /* 聲明指針變量 */

	ip = &a /* 指針變量的存儲(chǔ)地址 */

	fmt.Printf("a 變量的地址是: %x\n", &a)

	/* 指針變量的存儲(chǔ)地址 */
	fmt.Printf("ip 變量?jī)?chǔ)存的指針地址: %x\n", ip)

	/* 使用指針訪問(wèn)值 */
	fmt.Printf("*ip 變量的值: %d\n", *ip)
}

運(yùn)行結(jié)果

a 變量的地址是: c00000a0b0
ip 變量?jī)?chǔ)存的指針地址: c00000a0b0
*ip 變量的值: 20

空指針

當(dāng)一個(gè)指針被定義后沒(méi)有分配到任何變量時(shí),它的值為 nil。

nil 指針也稱為空指針。一個(gè)指針變量通??s寫(xiě)為 ptr。

package main

import "fmt"

func main() {
	var ip *int /* 聲明指針變量 */

	/* 指針變量的存儲(chǔ)地址 */
	fmt.Printf("ip 的值為: %x\n", ip)
}

運(yùn)行結(jié)果

ip 的值為: 0

空指針判斷

if(ptr != nil)     /* ptr 不是空指針 */
if(ptr == nil)    /* ptr 是空指針 */

指針數(shù)組

package main

import "fmt"

func main() {
	a := []int{10, 100, 200}
	// 遍歷數(shù)組
	for i := 0; i < len(a); i++ {
		fmt.Printf("a[%d] = %d\n", i, a[i])
	}
	fmt.Println("==================================")
	// 有一種情況,我們可能需要保存數(shù)組,這樣我們就需要使用到指針。
	// 以下聲明了整型指針數(shù)組:
	var ptr [3]*int
	for i := 0; i < len(a); i++ {
		/* 整數(shù)地址賦值給指針數(shù)組 */
		ptr[i] = &a[i]
	}
	for i := 0; i < len(ptr); i++ {
		fmt.Printf("a[%d] = %d\n", i, *ptr[i])
	}
}

運(yùn)行結(jié)果

a[0] = 10
a[1] = 100
a[2] = 200
==================================
a[0] = 10
a[1] = 100
a[2] = 200

指向指針的指針

如果一個(gè)指針變量存放的又是另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針變量。 指向指針的指針變量聲明格式

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

運(yùn)行結(jié)果

變量 a = 3000
指針變量 *ptr = 3000
指向指針的指針變量 **pptr = 3000

指針作為函數(shù)參數(shù)

package main

import "fmt"

func main() {
	var a = 3
	var b = 4
	fmt.Println("值傳遞運(yùn)行前a=", a, "b=", b)
	test1(a, b)
	fmt.Println("值傳遞運(yùn)行后a=", a, "b=", b)
	fmt.Println("===============================================")
	var i = 1
	var j = 2
	fmt.Println("引用傳遞運(yùn)行前i=", i, "j=", j)
	test2(&i, &j)
	fmt.Println("引用傳遞運(yùn)行后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
}

運(yùn)行結(jié)果

值傳遞運(yùn)行前a= 3 b= 4
值傳遞運(yùn)行后a= 3 b= 4
===============================================
引用傳遞運(yùn)行前i= 1 j= 2
引用傳遞運(yùn)行后i= 2 j= 1

結(jié)構(gòu)體

結(jié)構(gòu)體是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合。

結(jié)構(gòu)體表示一項(xiàng)記錄,比如保存圖書(shū)館的書(shū)籍記錄,每本書(shū)有以下屬性:

Title :標(biāo)題 Author : 作者 Subject:學(xué)科 ID:書(shū)籍ID

定義

type struct_variable_type struct {
   member definition
   member definition
   ...
   member definition
}

一旦定義了結(jié)構(gòu)體類型,它就能用于變量的聲明,語(yǔ)法格式如下:

variable_name := structure_variable_type {value1, value2...valuen}
或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
package main

import "fmt"

// 一、定義結(jié)構(gòu)體
type Books struct {
	title   string
	author  string
	subject string
	book_id int
}

func main() {

	// 創(chuàng)建一個(gè)新的結(jié)構(gòu)體
	fmt.Println(Books{"Go 語(yǔ)言", "Google", "Go 語(yǔ)言教程", 6495407})

	// 也可以使用 key => value 格式
	fmt.Println(Books{title: "Go 語(yǔ)言", author: "Google", subject: "Go 語(yǔ)言教程", book_id: 6495407})

	// 忽略的字段為 0 或 空
	fmt.Println(Books{title: "Go 語(yǔ)言", author: "Google"})

	fmt.Println("=========================")

	// 二、訪問(wèn)結(jié)構(gòu)體成員
	/* book 2 描述 */
	var Book2 Books
	Book2.title = "Python 教程"
	Book2.author = "Python"
	Book2.subject = "Python 語(yǔ)言教程"
	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("=========================")
	// 三、結(jié)構(gòu)體作為函數(shù)參數(shù)
	printBook(Book2)
	fmt.Println("=========================")
	// 四、結(jié)構(gòu)體指針
	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)
}

運(yùn)行結(jié)果

{Go 語(yǔ)言 Google Go 語(yǔ)言教程 6495407}
{Go 語(yǔ)言 Google Go 語(yǔ)言教程 6495407}
{Go 語(yǔ)言 Google  0}
=========================
Book 2 title : Python 教程
Book 2 author : Python
Book 2 subject : Python 語(yǔ)言教程
Book 2 book_id : 6495700
=========================
Book title : Python 教程
Book author : Python
Book subject : Python 語(yǔ)言教程
Book book_id : 6495700
=========================
Book title : Python 教程
Book author : Python
Book subject : Python 語(yǔ)言教程
Book book_id : 6495700

切片(Slice)

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

定義切片

  1. var identifier []type

  2. var slice1 []type = make([]type, len) 或者簡(jiǎn)寫(xiě) slice1 := make([]type, len) 指定長(zhǎng)度

  3. make([]T, length, capacity) 指定容量

package main

import "fmt"

func main() {
	// 切片初始化
	var slice = []int{1, 2, 3}
	// 從下標(biāo)startIndex到endIndex-1 下的元素 切片截取
	fmt.Println(slice[0:2])
	fmt.Println(slice[:2])
	fmt.Println(slice[0:])
	fmt.Println("=======================")
	// len() 和 cap() 函數(shù)
	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() 函數(shù)
	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() 復(fù)制
	/* 創(chuàng)建切片 numbers2 是之前切片的兩倍容量*/
	numbers2 := make([]int, len(numbers1), (cap(numbers1))*2)
	/* 拷貝 numbers1 的內(nèi)容到 numbers2 */
	copy(numbers2, numbers1)
	fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers2), cap(numbers2), numbers2)
}

運(yùn)行結(jié)果

[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去求一個(gè)slice的和。使用數(shù)組跟這個(gè)很類似
	nums := []int{2, 3, 4}
	sum := 0
	for _, num := range nums {
		sum += num
	}
	fmt.Println("sum:", sum)
	//在數(shù)組上使用range將傳入index和值兩個(gè)變量。上面那個(gè)例子我們不需要使用該元素的序號(hào),所以我們使用空白符"_"省略了。有時(shí)侯我們確實(shí)需要知道它的索引。
	for i, num := range nums {
		if num == 3 {
			fmt.Println("index:", i)
		}
	}
	//range也可以用在map的鍵值對(duì)上。
	kvs := map[string]string{"a": "apple", "b": "banana"}
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}
	//range也可以用來(lái)枚舉Unicode字符串。第一個(gè)參數(shù)是字符的索引,第二個(gè)是字符(Unicode的值)本身。
	for i, c := range "go" {
		fmt.Println(i, c)
	}
}

運(yùn)行結(jié)果

sum: 9
index: 1
a -> apple
b -> banana
0 103
1 111

Map(集合)

Map 是一種無(wú)序的鍵值對(duì)的集合。Map 最重要的一點(diǎn)是通過(guò) key 來(lái)快速檢索數(shù)據(jù),key 類似于索引,指向數(shù)據(jù)的值。

定義集合

/* 聲明變量,默認(rèn) map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函數(shù) */
map_variable := make(map[key_data_type]value_data_type)

如果不初始化 map,那么就會(huì)創(chuàng)建一個(gè) nil map。nil map 不能用來(lái)存放鍵值對(duì)

package main

import "fmt"

func main() {
	var countryCapitalMap = make(map[string]string)

	/* map插入key - value對(duì),各個(gè)國(guó)家對(duì)應(yīng)的首都 */
	countryCapitalMap["France"] = "巴黎"
	countryCapitalMap["Italy"] = "羅馬"
	countryCapitalMap["Japan"] = "東京"
	countryCapitalMap["India "] = "新德里"

	/*使用鍵輸出地圖值 */
	for country := range countryCapitalMap {
		fmt.Println(country, "首都是", countryCapitalMap[country])
	}

	/*查看元素在集合中是否存在 */
	capital, ok := countryCapitalMap["American"] /*如果確定是真實(shí)的,則存在,否則不存在 */
	/*fmt.Println(capital) */
	/*fmt.Println(ok) */
	if ok {
		fmt.Println("American 的首都是", capital)
	} else {
		fmt.Println("American 的首都不存在")
	}

	fmt.Println("========================")
	// delete() 函數(shù)
	for country := range countryCapitalMap {
		fmt.Println(country, "首都是", countryCapitalMap[country])
	}
	// 刪除元素
	delete(countryCapitalMap, "France")
	fmt.Println("法國(guó)條目被刪除")
	for country := range countryCapitalMap {
		fmt.Println(country, "首都是", countryCapitalMap[country])
	}
}

運(yùn)行結(jié)果

France 首都是 巴黎
Italy 首都是 羅馬
Japan 首都是 東京
India  首都是 新德里
American 的首都不存在
========================
India  首都是 新德里
France 首都是 巴黎
Italy 首都是 羅馬
Japan 首都是 東京
法國(guó)條目被刪除
Japan 首都是 東京
India  首都是 新德里
Italy 首都是 羅馬

遞歸函數(shù)

遞歸,就是在運(yùn)行的過(guò)程中調(diào)用自己

階乘

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
}

運(yùn)行結(jié)果

15 的階乘是 1307674368000

斐波那契數(shù)列

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

運(yùn)行結(jié)果

0	1	1	2	3	5	8	13	21	34

類型轉(zhuǎn)換

類型轉(zhuǎn)換用于將一種數(shù)據(jù)類型的變量轉(zhuǎn)換為另外一種類型的變量。

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

運(yùn)行結(jié)果

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

運(yùn)行結(jié)果

nokiaPhone
IPhone

錯(cuò)誤處理

Go 語(yǔ)言通過(guò)內(nèi)置的錯(cuò)誤接口提供了非常簡(jiǎn)單的錯(cuò)誤處理機(jī)制。

error類型是一個(gè)接口類型,這是它的定義

type error interface {
    Error() string
}

我們可以在編碼中通過(guò)實(shí)現(xiàn) error 接口類型來(lái)生成錯(cuò)誤信息。

函數(shù)通常在最后的返回值中返回錯(cuò)誤信息。使用errors.New 可返回一個(gè)錯(cuò)誤信息

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")
	}
	// 實(shí)現(xiàn)
	return f, nil
}

運(yùn)行結(jié)果

math: square root of negative number

并發(fā)

Go 語(yǔ)言支持并發(fā),我們只需要通過(guò) go 關(guān)鍵字來(lái)開(kāi)啟 goroutine 即可。

goroutine 是輕量級(jí)線程,goroutine 的調(diào)度是由 Golang 運(yùn)行時(shí)進(jìn)行管理的。

goroutine 語(yǔ)法格式:

go 函數(shù)名( 參數(shù)列表 )

Go 允許使用 go 語(yǔ)句開(kāi)啟一個(gè)新的運(yùn)行期線程, 即 goroutine,以一個(gè)不同的、新創(chuàng)建的 goroutine 來(lái)執(zhí)行一個(gè)函數(shù)。 同一個(gè)程序中的所有 goroutine 共享同一個(gè)地址空間。

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

運(yùn)行結(jié)果

hello
world
world
hello
hello
world
world
hello
hello

通道(channel)

通道(channel)是用來(lái)傳遞數(shù)據(jù)的一個(gè)數(shù)據(jù)結(jié)構(gòu)。

通道可用于兩個(gè) goroutine 之間通過(guò)傳遞一個(gè)指定類型的值來(lái)同步運(yùn)行和通訊。操作符 <- 用于指定通道的方向,發(fā)送或接收。如果未指定方向,則為雙向通道。 聲明一個(gè)通道,通道在使用前必須先創(chuàng)建:

ch := make(chan int)

注意:默認(rèn)情況下,通道是不帶緩沖區(qū)的。發(fā)送端發(fā)送數(shù)據(jù),同時(shí)必須有接收端相應(yīng)的接收數(shù)據(jù)。

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 發(fā)送到通道 c
}

運(yùn)行結(jié)果

-5 17 12

通道緩沖區(qū)

通道可以設(shè)置緩沖區(qū),通過(guò) make 的第二個(gè)參數(shù)指定緩沖區(qū)大小:

ch := make(chan int, 100)

帶緩沖區(qū)的通道允許發(fā)送端的數(shù)據(jù)發(fā)送和接收端的數(shù)據(jù)獲取處于異步狀態(tài),就是說(shuō)發(fā)送端發(fā)送的數(shù)據(jù)可以放在緩沖區(qū)里面,可以等待接收端去獲取數(shù)據(jù),而不是立刻需要接收端去獲取數(shù)據(jù)。

不過(guò)由于緩沖區(qū)的大小是有限的,所以還是必須有接收端來(lái)接收數(shù)據(jù)的,否則緩沖區(qū)一滿,數(shù)據(jù)發(fā)送端就無(wú)法再發(fā)送數(shù)據(jù)了。

注意:如果通道不帶緩沖,發(fā)送方會(huì)阻塞直到接收方從通道中接收了值。如果通道帶緩沖,發(fā)送方則會(huì)阻塞直到發(fā)送的值被拷貝到緩沖區(qū)內(nèi);如果緩沖區(qū)已滿,則意味著需要等待直到某個(gè)接收方獲取到一個(gè)值。接收方在有值可以接收之前會(huì)一直阻塞。

package main

import (
	"fmt"
)

func main() {
	// 這里我們定義了一個(gè)可以存儲(chǔ)整數(shù)類型的帶緩沖通道
	// 緩沖區(qū)大小為2
	ch := make(chan int, 2)

	// 因?yàn)?nbsp;ch 是帶緩沖的通道,我們可以同時(shí)發(fā)送兩個(gè)數(shù)據(jù)
	// 而不用立刻需要去同步讀取數(shù)據(jù)
	ch <- 1
	ch <- 2

	// 獲取這兩個(gè)數(shù)據(jù)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

運(yùn)行結(jié)果

1
2

遍歷通道與關(guān)閉通道

Go 通過(guò) range 關(guān)鍵字來(lái)實(shí)現(xiàn)遍歷讀取到的數(shù)據(jù),類似于與數(shù)組或切片。格式如下:

v, ok := <-ch
package main

import (
	"fmt"
)

func main() {
	c := make(chan int, 10)
	go fibonacci(cap(c), c)
	// range 函數(shù)遍歷每個(gè)從通道接收到的數(shù)據(jù),因?yàn)?nbsp;c 在發(fā)送完 10 個(gè)
	// 數(shù)據(jù)之后就關(guān)閉了通道,所以這里我們 range 函數(shù)在接收到 10 個(gè)數(shù)據(jù)
	// 之后就結(jié)束了。如果上面的 c 通道不關(guān)閉,那么 range 函數(shù)就不
	// 會(huì)結(jié)束,從而在接收第 11 個(gè)數(shù)據(jù)的時(shí)候就阻塞了。
	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
	}
	// 關(guān)閉通道
	close(c)
}

運(yùn)行結(jié)果

0
1
1
2
3
5
8
13
21
34

關(guān)于“Golang基礎(chǔ)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI