加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Go基础1

发布时间:2020-12-14 04:18:45 所属栏目:大数据 来源:网络整理
导读:基础语法: // --------------------------------------- 变量声明 var [名称] [类型] var name string 1)声明的变量一定要使用 2)声明同时初始化,可以不写后面类型: var sum = 17 多变量声明同其他语言var a,b int ? // 自动推导类型 [名称] := [值] na

基础语法:
// ---------------------------------------变量声明

var [名称] [类型]

var name string

1)声明的变量一定要使用

2)声明同时初始化,可以不写后面类型:var sum = 17

多变量声明同其他语言var a,b int

?

// 自动推导类型

[名称] := [值]

name := "Bill"

1)注意只能在函数局部使用

2)只能使用一次,用于初始化,第一次出现使用

?

//多重初始化

a,b,c := 10,"abc",1.0

?

//交换两个变量的值

A,b = b,a

?

//_匿名变量,丢弃数据不处理,一般是配合函数返回值使用

tmp,_ = i,j?? //tmp=10,go函数支持返回多值

?

//不同类型变量的声明

var(

?? a int = 1

?? b string = “abc”

)

// ---------------------------------------常量

const [名称] [类型] = 值

const? a int = 3

const? b? = “abc”

1、 不能使用自动推导

2、 类型是可选选项

3、 同时声明多个:const a,c = 1,false,"str" //多重赋值

?

常量还可以用作枚举(声明多个常量):

const (

??? Unknown = 0

??? Female = 1

??? Male = 2

)

?

?

// ---------------------------------------iota枚举

??? const (

??????? x = iota // x == 0

??????? y = iota // y == 1

??????? z = iota // z == 2

??????? w? // 这里隐式地说w = iota,因此w == 3。其实上面y和z可同样不用"= iota"

??? )

?

??? const v = iota // 每遇到一个const关键字,iota就会重置,此时v == 0

?

??? const (

??????? h,i,j = iota,iota,iota //h=0,i=0,j=0 iota在同一行值相同

??? )

?

??? const (

??????? a?????? = iota //a=0

??????? b?????? = "B"

??????? c?????? = iota???????????? //c=2

??????? d,e,f = iota,iota //d=3,e=3,f=3

??????? g?????? = iota???????????? //g = 4

??? )

???

??? const (

??????? x1 = iota * 10 // x1 == 0

??????? y1 = iota * 10 // y1 == 10

??????? z1 = iota * 10 // z1 == 20

??? )

1、 iota每隔一行,自动累计加1

2、 iota给常量赋值使用

3、 iota遇到const,重置为0

?

// ---------------------------------------注释

// 单行注释,CsCode快捷键Ctrl+/

/*

?Author by 多行注释

?我是多行注释

?*/

?

// ---------------------------------------?类型转换

分兼容的直接转换,和不兼容的利用类库转换

不兼容的一般会类似这样提示

cannot convert ?expression (type type_name) to type desctype_name

1、 兼容的可以直接转

type_name(expression)

mean = float32(sum) / float32(count)

var ch byte

ch = ‘a’

var t int

t = int(ch)//类型转换

2、 不兼容的可以利用函数strconv里面的方法进行转,一般会返回两个值,转换结果和报错信息

boolvalue,err := strconv.ParseBool("1")//int类型 转成 bool

i,err := strconv.Atoi(“123”) //string 类型 转成 int

?

?

// ---------------------------------------?变量输入

Var a int

fmt.Scan(&a)//输入值赋给a

?

?

// ---------------------------------------?类型别名type(把类型弄个自己的名字来用)

在结构体和方法里面会用到

Type 别名 类型

type bigint int64 //int64类型改名为bigint
var x bigint = 100//等价于var x int64 = 100
?
type (
??????myint int??? //int改名为myint
??????mystr string //string改名为mystr
)

?

// ---------------------------------------??运算符

大同小异,这里列一些和C#不同的

1、++和—只有后自增和后自减

2、位运算符多了<<和>>

3、赋值运算符<<=、>>=

4、返回变量存储地址:&

5、指针变量:*

/*? & 和 * 运算符实例 */

var a int = 4

?? var ptr *int

?? ptr = &a????/* ‘ptr‘ 包含了 ‘a‘ 变量的地址,*ptr就是a的值 */

?? fmt.Printf("a 的值为? %dn",a);

?? fmt.Printf("*ptr 为 %dn",*ptr);

a 的值为? 4

*ptr 为 4

?

一元运算符拥有最高的优先级,二元运算符的运算方向均是从左至右。

下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:

优先级

运算符

7

^????? !??

6

*?????? /??? %??? <<??? >>??? &????? &^

5

+????? -???? |????? ^

4

==?? !=?? <??? <=??? >=??? >

3

<-

2

&&

1

||

?

?

// ---------------------------------------??if语句

If

if a < 20 {

?????? fmt.Printf("a 小于 20n" )

?? }

//支持一个初始化表达式,初始化字句和条件表达式直接需要用分号分隔
????if b := 3; b == 3 {
????????fmt.Println("b==3")
??? }

????

If else

if a < 20 {//{不能跨行

???? ??fmt.Printf("a 小于 20n" );

?? } else if {//{不能跨行

fmt.Printf("a 不小于 20n" );

?? }else {//{不能跨行

fmt.Printf("a 不小于 20n" );

?? }

?

if嵌套

if 布尔表达式 1 {

?? /* 在布尔表达式 1 为 true 时执行 */

?? if 布尔表达式 2 {

????? /* 在布尔表达式 2 为 true 时执行 */

?? }

}

?

?

?

Switch:和C#比,没括号(go里面,加括号,加分号,保存后,VsCode会自动去掉)

switch var1 {

??? case val1:

??????? ...

case val2:

?????? ...

??? default:

??????? ...

}

?

Type Switch

switch x.(type){

??? case type:

?????? statement(s);?????

??? case type:

?????? statement(s);

??? /* 你可以定义任意个数的case */

??? default: /* 可选 */

?????? statement(s);

}

1. 支持多条件匹配

switch{

????case 1,2,3,4:

????default:

}

2. 不同的 case 之间不使用 break 分隔,默认只会执行一个 case。

3. 如果想要执行多个 case,需要使用 fallthrough 关键字(一般结尾加,没遇到break会继续执行下一个case分支),也可用 break 终止。

4、支持初始化语句

switch num := 1;num{

?? case 1:

?? default:

}

4、 switch可以没有条件,case放条件

score := 85

Switch{

Case score > 90:

fmt.mrintlc(“优秀”)

}

?

// ---------------------------------------??循环 for

有三种形式

1、for init; condition; post { }
2、for condition { }? //和while类似
3、for { } //相当于while(true),里面要加break跳出的
  • init: 一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量。
    • ????/* for 循环 */
    • ????for a := 0; a < 10; a++ {
    • ????????fmt.Printf("a 的值为: %dn",a)
    • ????}

?

????for a < b {

????????a++

????????fmt.Printf("a 的值为: %dn",a)

???? }

?

?

?

// ---------------------------------------??迭代器range相当于C#foreach

关键字 range 会返回两个值(可以选择定义一个变量只接受一个值),第一个返回值是元素的数组下标,第二个返回值是元素的值:

????s := "abc"
????for i := range s { //支持 string/array/slice/map。
????????fmt.Printf("%cn",s[i])//只接受下标i
????}
?
????for _,c := range s { // 忽略 index
????????fmt.Printf("%cn",c)
????}
?
????for i,c := range s {
????????fmt.Printf("%d,%cn",c)
????}

?

?

?

// ---------------------------------------? goto

用goto跳转到必须在当前函数内定义的标签:

func main() {
????for i := 0; i < 5; i++ {
????????for {
????????????fmt.Println(i)
????????????goto LABEL //跳转到标签LABEL,从标签处,执行代码
????????}
????}
?
????fmt.Println("this is test")
?
LABEL:
????fmt.Println("it is over")
}

?

?

// ---------------------------------------?函数

func function_name( [parameter list] ) [return_types] {

?? 函数体

}

  • func:函数由 func 开始声明
  • function_name:函数名称,函数名和参数列表一起构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。
  • 函数名首字母小写即为private,大写即为public
    • /* 函数返回两个数的和 */
    • func max(num1,num2 int) int {
    • ???/* 声明局部变量 */
    • ???var result int
    • ???Result = num1 + num2
    • ???return result
    • }
?

多个返回值

  • /* 函数返回两个数的和 */
  • func swap(num1 string,num2 int) (string,int) {
  • ???return num1,num2
  • }

?

不定参数类型

不定参数是指函数传入的参数个数为不定数量。为了做到这点,首先需要将函数定义为接受不定参数类型:

//形如...type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数
func Test(args ...int) {
????for _,n := range args { //遍历参数列表
????????fmt.Println(n)
????}
}
?
func main() {
????//函数调用,可传0到多个参数
????Test()
????Test(1)
????Test(1,4)
}

?

2) 不定参数的传递

func MyFunc01(args ...int) {
????fmt.Println("MyFunc01")//len(args)
????for _,n := range args { //遍历参数列表
????????fmt.Println(n)
????}
}
?
func MyFunc02(args ...int) {
????fmt.Println("MyFunc02")
????for _,n := range args { //遍历参数列表
????????fmt.Println(n)
????}
}
?
func Test(args ...int) {
????MyFunc01(args...)???? //按原样传递,Test()的参数原封不动传递给MyFunc01
????MyFunc02(args[1:]...) //Test()参数列表中,第1个参数及以后的参数传递给MyFunc02
}
?
func main() {
????Test(1,3) //函数调用
}

?

返回写法比较多样

单个返回值

func Test01() int { //方式1
????return 250
}
?
//官方建议:最好命名返回值,因为不命名返回值,虽然使得代码更加简洁了,但是会造成生成的文档可读性差
func Test02() (value int) { //方式2,给返回值命名
????value = 250
????return value
}
?
func Test03() (value int) { //方式3,给返回值命名
????value = 250
????return
}
?

多个返回值

func Test01() (int,string) { //方式1
????return 250,"sb"
}
?
func Test02() (a int,str string) { //方式2,给返回值命名
????a = 250
????str = "sb"
????return

}

?

// ---------------------------------------?函数类型(有点像C#的委托)

在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型。

?

type FuncType func(int,int) int //声明一个函数类型,func后面没有函数名
?
//函数中有一个参数类型为函数类型:f FuncType
func Calc(a,b int,f FuncType) (result int) {//Calc是执行的
????result = f(a,b) //通过调用f()实现任务
????return
}
?
//实际调用的函数实现
func Add(a,b int) int {
????return a + b
}
?
//实际调用的函数实现
func Minus(a,b int) int {
????return a - b
}
?
func main() {
????//函数调用,第三个参数为函数名字,此函数的参数,返回值必须和FuncType类型一致
????result := Calc(1,1,Add)
????fmt.Println(result) //2
?
????var f FuncType = Minus
????fmt.Println("result = ",f(10,2)) //result =? 8
}

?

回调函数

就是利用函数类型实现

实际调用的函数是函数类型的实现

调用那个实现函数类型的是执行的主体

// ---------------------------------------?匿名函数与闭包

所谓闭包就是一个函数“捕获”了和它在同一作用域的其它常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

闭包需要匿名函数来实现(都是匿名函数)

在Go语言里,所有的匿名函数(Go语言规范中称之为函数字面量)都是闭包。匿名函数是指不需要定义函数名的一种函数实现方式。

func main() {
????i := 0
????str := "mike"
?
????//方式1,先定义,再赋函数
????f1 := func() { //匿名函数,无参无返回值
????????//引用到函数外的变量
????????fmt.Printf("方式1:i = %d,str = %sn",str)
????}
?
????f1() //函数调用
?
????//方式1的另一种方式
????type FuncType func() //声明函数类型,无参无返回值
????var f2 FuncType = f1//这里f1就是没参数名的函数
????f2() //函数调用
?
????//方式2,直接赋函数
????var f3 FuncType = func() {
????????fmt.Printf("方式2:i = %d,str)
????}
????f3() //函数调用= func() {
?
????//方式3,定义完了加()就是调用
????func() { //匿名函数,无参无返回值
????????fmt.Printf("方式3:i = %d,str)
????}() //别忘了后面的(),()的作用是,此处直接调用此匿名函数
?
????//方式4,匿名函数,有参有返回值
????v := func(a,b int) (result int) {
????????result = a + b
????????return
????}(1,1) //别忘了后面的(1,1),(1,1)的作用是,此处直接调用此匿名函数, 并传参
????fmt.Println("v = ",v)
?
}

?

// ---------------------------------------?数组

var variable_name [SIZE]variable_type

var balance [10]float32

var balance = [5]float32{1000.0,2.0,3.4,7.0,50.0}//初始化

/* 未定义长度的数组只能传给不限制数组长度的函数 */

/* 定义了长度的数组只能传给限制了相同数组长度的函数 */

?

?

?

?

二维数组

var arrayName [ x ][ y ]variable_type

//初始化

a = [3][4]int{?

?{0,3},?? /*? 第一行索引为 0 */

?{4,5,6,7},?? /*? 第二行索引为 1 */

?{8,9,10,11},?? /* 第三行索引为 2 */

}

?

?

?

// ---------------------------------------?结构体

type struct_variable_type struct {

?? member definition;

?? member definition;

?? ...

?? member definition;

}

?

type Books struct {

?? title string

?? author string

?? subject string

?? book_id int

}

?

// 创建一个新的结构体
fmt.Println(Books{"Go 语言","www.runoob.com","Go 语言教程",6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言",author: "www.runoob.com",subject: "Go 语言教程",book_id: 6495407})
?
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言",author: "www.runoob.com"})

?

var Book1 Books??????? /* 声明 Book1 为 Books 类型 */

/* book 1 描述 */

Book1.title = "Go 语言"

Book1.author = "www.runoob.com"

Book1.subject = "Go 语言教程"

Book1.book_id = 6495407

?

// ---------------------------------------?defer 延迟调用

关键字 defer ?于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行。注意,defer语句只能出现在函数或方法的内部。
func main() {
????defer fmt.Println("this is a defer") //main结束前调用
fmt.Println("this is a test")
????/*
????????运行结果:
????????this is a test
????????this is a defer
????*/
}
?

defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后。

多个defer执行顺序

以LIFO(后进先出)的顺序执行。哪怕函数或某个延迟调用发生错误,这些调用依旧会被执?。

defer和匿名函数结合使用(注意里面的变量是否是闭包引用)

func main() {
????a,b := 10,20
????defer func(x int) { // a以值传递方式传给x
????????fmt.Println("defer:",x,b) // b 闭包引用,a是外部传参进来,已经传进来10,只是没执行
????}(a)
?
????a += 10
????b += 100
?
????fmt.Printf("a = %d,b = %dn",a,b)
?
????/*
????????运行结果:
????????a = 20,b = 120
????????defer: 10 120
????*/
}

// --------------------------------------- 获取命令行参数

import (
????"fmt"
????"os"????//os.Args所需的包
)
func main() {
????args := os.Args //获取用户输入的所有参数,字符串
?
????//如果用户没有输入,或参数个数不够,则调用该函数提示用户
????if args == nil || len(args) < 2 {
????????fmt.Println("err: xxx ip port")
????????return
????}
????ip := args[1]?? //获取输入的第一个参数
????port := args[2] //获取输入的第二个参数
fmt.Printf("ip = %s,port = %sn",ip,port)
}

?

// ---------------------------------------不同作用域的同名变量

在不同作用域可以声明同名的变量,其访问原则为:在同一个作用域内,就近原则访问最近的变量,如果此作用域没有此变量声明,则访问全局变量,如果全局变量也没有,则报错。

?

?

基础数据类型

2.4.1 分类

Go语言内置以下这些基础类型:

类型

名称

长度

零值

说明

bool

布尔类型

1

false

其值不为真即为家,不可以用数字代表true或false

byte

字节型

1

0

uint8别名,放英文字符‘a’

rune

字符类型

4

0

专用于存储unicode编码,等价于uint32,可以放中文字符‘中’//20013

int,uint

整型

4或8

0

32位或64位

int8,uint8

整型

1

0

-128 ~ 127,0 ~ 255

int16,uint16

整型

2

0

-32768 ~ 32767,0 ~ 65535

int32,uint32

整型

4

0

-21亿 ~ 21 亿,0 ~ 42 亿

int64,uint64

整型

8

0

?

float32

浮点型

4

0.0

小数位精确到7位

float64

浮点型

8

0.0

小数位精确到15位

complex64

复数类型

8

?

?

complex128

复数类型

16

?

?

uintptr

整型

4或8

?

?以存储指针的uint32或uint64整数

string

字符串

?

""

utf-8字符串,str[0]、str[1]

?

格式化输出输入

格式

含义

%%

一个%字面量

%b

一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数

%c

字符型。可以把输入的数字按照ASCII码相应转换为对应的字符

%d

一个十进制数值(基数为10)

%e

以科学记数法e表示的浮点数或者复数值

%E

以科学记数法E表示的浮点数或者复数值

%f

以标准记数法表示的浮点数或者复数值

%g

以%e或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出

%G

以%E或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出

%o

一个以八进制表示的数字(基数为8)

%p

以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示

%q

使用Go语法以及必须时使用转义,以双引号括起来的字符串或者字节切片[]byte,或者是以单引号括起来的数字

%s

字符串。输出字符串中的字符直至字符串中的空字符(字符串以‘‘结尾,这个‘‘即空字符)

%t

以true或者false输出的布尔值

%T

使用Go语法输出的值的类型

%U

一个用Unicode表示法表示的整型码点,默认值为4个数字字符

%v

使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的String()方式输出的自定义值,如果该方法存在的话

%x

以十六进制表示的整型值(基数为十六),数字a-f使用小写表示

%X

以十六进制表示的整型值(基数为十六),数字A-F使用小写表示

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读