golang笔记

#Go语言

golang 下载、安装 官网下载地址

tar -xzf go1.16.5.linux-amd64.tar.gz -C /usr/local
echo "export PATH=$PATH:/usr/local/go/bin" >> /etc/profile
source /etc/profile

关键字 下面列举了 Go 代码中会使用到的 25 个关键字或保留字:

break

default

func

case

defer

go

map

chan

else

goto

package

const

fallthrough

if

range

continue

for import

return

var

除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:

append

bool

byte

cap

close

complex

complex64

complex128

uint16

copy

false

float32

float64

imag

int

int8

int16

uint32

int32

int64

iota

len

make

new

nil

panic

uint64

print

println

real

recover

string

true

uint

uint8

uintptr

程序一般由关键字、常量、变量、运算符、类型和函数组成。

程序中可能会使用到这些分隔符:括号 (),中括号 [] 和大括号 {}。

程序中可能会使用到这些标点符号:.、,、;、: 和 …。

格式化字符串

package main

import (
	"fmt"
)

func main() {
	// %d 表示整数型数字,%s 表示字符串
	var stockcode=123
	var enddate="2021-06-29"
	var url="Code=%d&endDate=%s"
	var target_url=fmt.Sprintf(url,stockcode,enddate)
	fmt.Println(target_url)
}

变量

格式:

var  identifier type
var identifier1, identifier2 type	# 可一次声明多个变量

实例:

package main
import "fmt"
func main() {
	var a string = "Hello"
	fmt.Println(a)
	
	var b, c int =1, 2
	fmt.Println(b, c)
}

变量声明

第一种,指定变量类型,如果没有初始化,则变量默认为零值(零值就是变量没有做初始化时系统默认设置的值)

实例:

package main
import "fmt"
func main() {
	// 声明一个变量并初始化
	var a = "Hello"
	fmt.Println(a)
	
	// 没有初始化就为零值
	var b int
	fmt.Println(b)
	
	// bool 零值为false
	var c bool
	fmt.Println(c)
}
  • 数值类型(包括complex64/128)为 0

  • 布尔类型为 false

  • 字符串为 ""(空字符串)

  • 以下几种类型为 nil

var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口

第二种,根据值自行判定变量类型。 格式:

var v_name = value

实例:

package main
import "fmt"
func main(){
	var d = true
	fmt.Println(d)
}

第三种,省略var,注意:= 左侧如果没有声明新的变量,就产生编译错误, 格式:

v_name := value

实例:

package main
import "fmt"
func main(){
	// 这种不带声明格式的只能在函数体中出现
	f := "Hello"	// 等于 var f string="Hello" 或 var f = "Hello"
	fmt.Println(f)
}

多变量声明

// 类型相同的多个变量,非全局变量
var v_name1, v_name2, v_name 3 type
v_name1, v_name2, v_name3 = value1, value2, value3

var v_name1, v_name2, v_name3 = value1, value2, value3

v_name1, v_name2, v_name3 := value1, value2, value3

// 下面这种因式分解关键字的写法一般用于声明全局变量
var (
	v_name1 v_type1
	v_name2 v_type2
)

实例:

package main

var x, y int
var (
	a int
	b bool
    j string = "string"
)

var c, d int = 1, 2
var e, f = 123, "Hello"

func main() {
	g, h := 321, "Hello World"
	println(a, b, c, d, e, f, g, h, x, y, j)
}

常量

指在程序运行时,不会被修改的量,常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型 格式:

const identifier [type] = value	# [type]类型可省略,编译器可以根据变量的值来判断其类型
const c_name1, cname2 = value1, value2	# 多个相同类型的声明

实例:

package main
import "fmt"

func main() {
	const LENGTH int =  10
	const WIDTH int = 5
	var area int
	const a, b, c = 1, false, "Hello"
	
	area = LENGTH * WIDTH
	fmt.Printf("面积为:%d", area)
	println()
	println(a, b, c)
}

unsafe.Sizeof() 查看类型所占字节大小

iota

iota,特殊常量,可以认为是一个可以被编译器修改的常量。 iota在const关键字出现时将被重置为0(const内部的的第一行之前),const中每新增加一行常量声明将使iota计数一次(iota可以理解为const语句中的行索引)

const (
	a = iota
	b = iota
	c = iota
)

每一个iota等于0,每当Iota在新的一行被使用时,它的值都会自动加1,所以a=0,b=1,c=2 也可以按下面简写

const (
	a = iota
	b
	c
)

iota用法实例:

package main
import "fmt"

func main() {
	const (
		a = iota	// a = 0
		b			// 1
		c			// 2
		d = "Hello"	// 独立值,但iota继续+1 
		e			// e = "Hello"  iota继续+1 
		f = 100		// 独立值,iota继续+1 
		g			// g = 100 iota继续+1 
		h = iota	// 7 恢复计数
		i			// 8
	)
	fmt.Println(a,b,c,d,e,f,g,h,i)
}

运算符

运算符用于在程序运行时执行数字或逻辑运算 go语言内置的运算符有:

  • 算术运算符

  • 关系运算符

  • 逻辑运算符

  • 位运算符

  • 赋值运算符

  • 其它运算符

算术运算符

下表列出了所有Go语言的算术运算符。假定 A 值为 10,B 值为 20。

运算符
描述
实例

+

相加

A + B 输出结果 30

-

相减

A - B 输出结果 -10

*

相乘

A * B 输出结果 200

/

相除

B / A 输出结果 2

%

求余

B % A 输出结果 0

++

自增

A++ 输出结果 11

--

自减

A-- 输出结果 9

实例:

package main

import "fmt"

func main() {
	var a int = 15
	var b int = 12
	var c int

	c = a + b
	fmt.Printf("a+b=%d", c)
	c = a - b
	fmt.Printf("a-b=%d", c)
	c = a * b
	fmt.Printf("a*b=%d", c)
	c = a / b
	fmt.Printf("a/b=%d", c)
	c = a % b
	fmt.Printf("a/b=%d", c)
	a++
	fmt.Printf("a++=%d",a)
	b--
	fmt.Printf("b--=%d",b)
}

关系运算符

下表列出了所有Go语言的关系运算符。假定 A 值为 10,B 值为 20。

运算符
描述
实例

==

检查两个值是否相等,如果相等返回 True 否则返回 False。

(A == B) 为 False

!=

检查两个值是否不相等,如果不相等返回 True 否则返回 False。

(A != B) 为 True

>

检查左边值是否大于右边值,如果是返回 True 否则返回 False。

(A > B) 为 False

<

检查左边值是否小于右边值,如果是返回 True 否则返回 False。

(A < B) 为 True

>=

检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。

(A >= B) 为 False

<=

检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

(A <= B) 为 True

逻辑运算符逻辑运算符

下表列出了所有Go语言的逻辑运算符。假定 A 值为 True,B 值为 False。

运算符
描述
实例

&&

逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。

(A && B) 为 False

||

逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。

(A || B) 为 True

!

逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。

!(A && B) 为 True

位运算符

位运算符对整数在内存中的二进制位进行操作。

下表列出了位运算符 &, |, 和 ^ 的计算:

假定 A = 60; B = 13; 其二进制数转换为:

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

Go 语言支持的位运算符如下表所示。假定 A 为60,B 为13:

运算符
描述
实例

&

按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与(相同位置均为1)。

(A & B) 结果为 12, 二进制为 0000 1100

|

按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或(把两个数二进制为1的部分合并)

(A| B) 结果为 61, 二进制为 0011 1101

^

按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。(只保留二进制中不同位置的1)

(A ^ B) 结果为 49, 二进制为 0011 0001

<<

左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。

A << 2 结果为 240 ,二进制为 1111 0000

>>

右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。

A >> 2 结果为 15 ,二进制为 0000 1111

赋值运算符

下表列出了所有Go语言的赋值运算符。

运算符
描述
实例

=

简单的赋值运算符,将一个表达式的值赋给一个左值

C = A + B 将 A + B 表达式结果赋值给 C

+=

相加后再赋值

C += A 等于 C = C + A

-=

相减后再赋值

C -= A 等于 C = C - A

*=

相乘后再赋值

C *= A 等于 C = C * A

/=

相除后再赋值

C /= A 等于 C = C / A

%=

求余后再赋值

C %= A 等于 C = C % A

<<=

左移后赋值

C <<= 2 等于 C = C << 2

>>=

右移后赋值

C >>= 2 等于 C = C >> 2

&=

按位与后赋值

C &= 2 等于 C = C & 2

^=

按位异或后赋值

C ^= 2 等于 C = C ^ 2

|=

按位或后赋值

C |= 2 等于 C = C | 2

其他运算符

下表列出了Go语言的其他运算符。

运算符
描述
实例

&

返回变量存储地址

&a; 将给出变量的实际地址。

*

指针变量。

*a; 是一个指针变量

运算符优先级

有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:

优先级
运算符

* / % << >> & &^

+ - | ^

== != < <= > >=

&&

||

当然,你可以通过使用括号来临时提升某个表达式的整体运算优先级。

条件语句

条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句。 Go 语言提供了以下几种条件判断语句:

语句
描述

if 语句

if 语句 由一个布尔表达式后紧跟一个或多个语句组成。

if...else 语句

if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。

if 嵌套语句

你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。

switch 语句

switch 语句用于基于不同条件执行不同动作。

select 语句

select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断。

if语句

if语句由布尔表达式后紧跟一个或多个语句组成。 语法结构如下:

if 布尔表达式 {
	/* 在表达式为true时执行*/
}

实例:

package main
import "fmt"

func main() {
	var a int = 10
	
	if a < 20 {
		fmt.Printf("a 小于 20\n")
	}
	fmt.Printf("a的值为:%d", a)
}

if...else语句

语法结构如下:

if 布尔表达式 {
	/* 在表达式为 true 时执行*/
} else {
	/* 在表达式为 false 时执行*/
}

示例:

package main
import "fmt"
func main() {
	var a int = 10
	if a > 20 {
		fmt.Print("a大于20")
	} else {
		fmt.Print("a小于20")
	}
	fmt.Print("a的值是:%d", a)
}

if语句嵌套

语法结构如下:

if 布尔表达式1 {
	/* 在表达式1为 true 时执行*/
	if 布尔表达式2 {
		/* 在表达式为 true 时执行*/
	}
}

示例:

package main
import "fmt"
func main() {
	var a int = 10
	var b int = 20
	if a == 10 {
		if b == 20 {
			fmt.Print("a的值是10,b的值是20")
		}
	}
}

switch语句

switch 语句用于基于不同条件执行不同动作,每个case分支都是唯一的,从上至下逐一测试,直到匹配为止。 switch 语句执行的过程从上至下,直到找匹配项,匹配项后面也不需要再加break。 switch 语句默认情况下case最后自带break语句,匹配成功后就不会执行其它case,如果需要执行后面的case,可使用fallthrough。

语法结构:

swithc var1 {
	case val1:
		...
	case val2:
		...
	case val3:
		...
	default:
		...
}

变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。

示例:

package main
import "fmt"

func main() {
	var grade string = "B"
	var marks int = 90
	
	switch marks {
		case 90: grade = "A"
		case 80: grade = "B"
		case 50,60,70 : grade ="C"
		defaut: grade = "D"
	}
	
	switch {
		case grade == "A" :
			fmt.Printf("优秀!\n")
		case grade == "B", grade == "C" :
			fmt.Printf("良好\n")
		case grade == "D" :
			fmt.Printf("及格\n")
		case grade == "F" :
		    fmt.Printf("不及格\n")
		default:
			fmt.Printf("差\n")
	}	
	fmt.Printf("你的等级是:%s", grade)
}

Type Switch switch 语句还可以被用于type-switch来判断某个interface变量中实际存储的变量类型。 Type Swithc语法结构如下:

swithc x.(type){
	case type:
		statement(s);
	case type:
		statement(s);
		/* 你可以定义任意个数的case */
	default: /* 可选 */
		statement(s)
}

实例:

package main
import "fmt"

func main() {
	var x interface{}
	
	switch i := x.(type) {
		case nil:
			fmt.Printf("x的类型是: %T", i)
		case int:
			fmt.Printf("x是int型")
		case float64:
			fmt.Printf("x是float64型")
		case bool, string:
			fmt.Printf("x是bool或string型")
		default:
			fmt.Printf("x的类型未知")
	}
}

fallthrough 使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。

实例:

package main  
import "fmt"  
  
func main() {  
  
    switch {  
    case false:  
            fmt.Println("1、case 条件语句为 false")  
            fallthrough  
    case true:  
            fmt.Println("2、case 条件语句为 true")  
            fallthrough  
    case false:  
            fmt.Println("3、case 条件语句为 false")  
            fallthrough  
    case true:  
            fmt.Println("4、case 条件语句为 true")  
    case false:  
            fmt.Println("5、case 条件语句为 false")  
            fallthrough  
    default:  
            fmt.Println("6、默认 case")  
    }  
}

select 语句

select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。

select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。

语法 Go 编程语言中 select 语句的语法如下:

select {
    case communication clause  :
       statement(s);      
    case communication clause  :
       statement(s);
    /* 你可以定义任意数量的 case */
    default : /* 可选 */
       statement(s);
}

以下描述了 select 语句的语法:

  • 每个 case 都必须是一个通信

  • 所有 channel 表达式都会被求值

  • 所有被发送的表达式都会被求值

  • 如果任意某个通信可以进行,它就执行,其他被忽略。

  • 如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。 否则: 如果有 default 子句,则执行该语句。 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。

实例

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):  // same as: 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")  
   }      
}

循环语句

在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。

Go 语言提供了以下几种类型循环处理语句:

循环类型
描述

for 循环

重复执行语句块

循环嵌套

在 for 循环中嵌套一个或多个 for 循环

循环控制语句 循环控制语句可以控制循环体内语句的执行过程。

GO 语言支持以下几种循环控制语句:

控制语句
描述

break 语句

经常用于中断当前 for 循环或跳出 switch 语句

continue 语句

跳过当前循环的剩余语句,然后继续进行下一轮循环。

goto 语句

将控制转移到被标记的语句。

无限循环 实例:

package main
import "fmt"

func main() {
	for true {
		fmt.Printf("无限循环语句。\n");
	}
}

for 循环 go语言的for循环有3种形式,只有其中一种使用分号

for init; condition; post { }

for condition { }

for { }
  • init: 一般为赋值表达式,给控制变量赋初值;

  • condition: 关系表达式或逻辑表达式,循环控制条件;

  • post: 一般为赋值表达式,给控制变量增量或减量。

for语句执行过程如下:

  • 先对表达式1赋初值;

  • 判断赋值表达式init是否满足给定条件,若其值为true,满足循环条件,则执行循环体内语句,然后执行post,进行第二次循环,再判断condition;否则判断condition的值为false,不满足条件,终止for循环,执行循环体外的语句。

实例: 计算1-10之和

package main

import "fmt"

func main() {
	sum := 0
	for i :=0; i <= 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}

当sum小于等于10时,计算sum自相加的结果

package main
import "fmt"

func main() {
	sum := 1
	for ; sum <=10; {
		sum += sum
	}
	fmt.Println(sum)
	
	// 也可以写成下面这样,类似while循环
	for sum <= 10 {
		sum += sum
	}
	fmt.Println(sum)
}

无限循环

package main
import "fmt"
func main() {
	sum := 0
	for {
		sum++
		fmt.Println(sum) // 无限循环输出这个值
	}
	fmt.Println(sum) // 不会执行到这里
}

循环嵌套

package main
import "fmt"

func main() {
	var i, j int
	for i = 2;i < 100; i++ {
		for j = 2; j <= (i/j); j++ {
			if( i%j == 0 ) {
				break;
			}
		}
		
		if(j > (i/j)) {
			fmt.Printf("%d 是素数\n", i);
		}
	}
}

break语句 Go 语言中 break 语句用于以下两方面:

  • 用于循环语句中跳出循环,并开始执行循环之后的语句。

  • break 在 switch(开关语句)中在执行一条 case 后跳出语句的作用。

  • 在多重循环中,可以用标号 label 标出想 break 的循环。

语法格式如下:

break;

实例:

package main
import "fmt"

func main() {
	var a int  = 10
	
	for a < 20 {
		fmt.Printf("a的值是: %d\n", a);
		a++;
		if a > 15 {
			break;	//如果a大于15,则跳出循环
		}
	}
}

continue 语句

continue 语句 有点像 break 语句。但是 continue 不是跳出循环,而是跳过当前循环执行下一次循环语句。 for 循环中,执行 continue 语句会触发 for 增量语句的执行。 在多重循环中,可以用标号 label 标出想 continue 的循环

goto 语句

函数

函数是基本的代码块,用于执行一个任务。 Go 语言最少有个 main() 函数。 你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。 函数声明告诉了编译器函数的名称,返回类型,和参数。 Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。

函数格式:

func function_name( [parameter list] ) [return_types] {
	函数体
}

定义解析:

  • func:函数由 func 开始声明

  • function_name:函数名称,参数列表和返回值类型构成了函数签名。

  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。

  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。

  • 函数体:函数定义的代码集合。

实例: 以下实例为max() 函数的代码,该函数传入两个整形参数num1和num2,并返回两个参数的最大值;

func max(num1, num2 int) int {
	var result int
	
	if (num1 > num2) {
		result = num1
	} else {
		result = num2
	}
	return result
}

函数调用:

package main
import "fmt"

func main() {
	var a int = 100
	var b int = 200
	var ret int
	
	// 调用函数
	ret = max(a, b)
	
	fmt.Printf("最大值是: %d", ret)
}

// 定义函数,返回传入的两个参数的最大值
func max(num1, num2 int) int {
	var result int
	if (num1 > num2) {
		result = num1
	} else {
		result = num2
	}
	return result
}

返回多个值:

package main
import "fmt"

func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("Hello", "World")
	fmt.Println(a,b)
}

函数值传递值

package main
import "fmt"

func main() {
	var a int = 10
	var b int = 20
	
	fmt.Printf("交换前a的值为: %d\n", a)
	fmt.Printf("交换前b的值为: %d\n", b)
	
	w
}

func swap(x, y int) int {
	var temp int
	 
	temp = x // 将x的值赋给temp
	x = y	// 将y的值赋给x
	y = temp // 将temp的值赋给y
	return temp;
}

最后更新于