go语言基础
Posted 一只小阿大:)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言基础相关的知识,希望对你有一定的参考价值。
目录
- go安装
- 语言结构
- 行分隔符
- 注释
- 标识符
- 格式化字符串
- 数据类型
- “var”与“:=”的区别
- 变量
- 值类型和引用类型
- 数据交换
- iota
- 运算符
- 条件语句
- 循环
- 函数
- 函数闭包的简单使用以及获取键盘输入
- 语言变量作用域
- 数组
- 数组定义
- 指针
- 结构体
- 切片(Slice)
go安装
参0照菜鸟教程 Go 语言环境安装
语言结构
需要注意的一点是 不能单独放在一行,所以以下代码在运行时会产生错误:
package main
import "fmt"
func main()
//错误, 不能在单独的行上
fmt.Println("Hello, World!")
行分隔符
格式跟python一样,不需要分号结尾
因为go的编译器会自动添加,如果需要多个语句在同一行,就需要分号了,但实际开发过程中不提倡这么写
注释
跟c语言一样的,单行// 多行/**/
标识符
也就是命名变量的时候是否合法
不合法的:
1ab(以数字开头)
case(Go 语言的关键字)
a+b(运算符是不允许的)
格式化字符串
package main
import (
"fmt"
)
func main()
// %d 表示整型数字,%s 表示字符串
var stockcode=123
var enddate="2020-12-31"
var url="Code=%d&endDate=%s"
var target_url=fmt.Sprintf(url,stockcode,enddate)
fmt.Println(target_url)
Operation results:
Code=123&endDate=2020-12-31
数据类型
我测试了一下如果超过变量类型存放的数据大小会怎样
package main
import "fmt"
func main()
var a uint8 = -1
//查看变量类型
fmt.Printf("type = %t\\n",a)
发现go语言有个参数边界检测提示
“var”与“:=”的区别
定义变量格式:
var variableName type = value
定义了一个int类型的变量number,初始化为10
var number int = 10
由于go语言设计者觉得这样比较繁琐
所以缩短成了 var variableName = value ,这样直接忽略掉了变量类型
然后继续简化成了 variableName := value
相当于var variableName = value 语句和variableName := value语句等同
变量
单变量声明
第一种,指定变量类型,如果没有初始化,则变量默认为零值。
go语言变量未初始化的初始值
数值类型(包括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 声明过了
如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误
多变量声明
package main
var x, y int
var ( // 这种因式分解关键字的写法一般用于声明全局变量
a int
b bool
)
var c, d int = 1, 2
var e, f = 123, "hello"
//这种不带声明格式的只能在函数体中出现
//g, h := 123, "hello"
func main()
g, h := 123, "hello"
println(x, y, a, b, c, d, e, f, g, h)
Operation results:
0 0 0 false 1 2 123 hello 123 hello
值类型和引用类型
所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值
当使用等号 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝
go语言可以像c语言一样操作地址,用了&取地址符
值类型变量的值存储在堆中
更复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存。
一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个字所在的位置。
当使用赋值语句 r2 = r1 时,只有引用(地址)被复制。
如果 r1 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,r2 也会受到影响
数据交换
如果你想要交换两个变量的值,则可以简单地使用 a, b = b, a,两个变量的类型必须是相同。
这样就不需要加个变量Buffer了。
往常c语言值的交换,就是Buffer = a , a = b ,b = Buffer
iota
iota
常用来设置枚举类型
package main
import "fmt"
func main()
const (
ColorRed = iota
ColorOrange
ColorYellow
ColorGrassland
ColorCyan
ColorBlue
ColorPurple
)
fmt.Println(ColorOrange)
fmt.Println(ColorPurple)
const (
a = iota
b
)
fmt.Println(a)
fmt.Println(b)
Opetion results:
1
6
0
1
运算符
跟c语言没区别,就不想写了
条件语句
多了个select(随机执行),是为了避免饥饿问题
一般配合通道(chan)一起使用
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")
循环
循环嵌套就循环套循环,没多大区别
循环控制语句也没啥区别,也是break,continue,goto
函数
函数定义格式
func function_name( [parameter list] ) [return_types]
函数体
package main
import "fmt"
func test(num1 int,num2 int) int
return num1+num2
func main()
fmt.Printf("total num = %d",test(1,2))
Opetion results:
total num = 3
go语言的函数返回值是可以多个函数返回值的
package main
import "fmt"
// 函数名 参数 参数类型 返回值类型
func test(num1 int,num2 int) (int,string)
return num1+num2,"nihao"
func main()
a,b := test(1,2)
fmt.Printf("total num = %d ,string = %s",a,b)
Operation results:
total num = 3 ,string = nihao
函数闭包的简单使用以及获取键盘输入
为什么要使用函数闭包?
因为使用函数闭包可以减少全局变量使用,下一次进入闭包函数,闭包函数中的变量值不会更改,相当于全局变量了
简单使用:
package main
import "fmt"
func test() func() string
return func() string
var name string
fmt.Println("Please input name")
fmt.Scanf("%s",&name)
fmt.Println(name)
return name
func main()
name := test()
fmt.Println(name())
Operation results:
Please input name
Finny
Finny
Finny
闭包意义体现,以及执行步骤:
看完下面例子,会发现闭包函数中的变量不会释放
package main
import (
"fmt"
)
//定义了一个闭包函数
func adder(a int) func(int) int
num := a //变量初始化
fmt.Println(num)
return func(x int) int //闭包函数,需要注意的是闭包函数返回值
num += x
// fmt.Println(num)
return num
func main()
myAdder := adder(10)
// 从1加到5
for i := 1; i <= 5; i++
myAdder(i)
fmt.Println(myAdder(0))
// 再加上5
fmt.Println(myAdder(5))
Operation results:
10
25
30
为什么闭包不会被垃圾回收
为什么闭包不会被垃圾回收
因此闭包会长期占用内存资源,可能会导致内存泄漏
语言变量作用域
Go 语言中变量可以在三个地方声明:
函数内定义的变量称为局部变量
函数外定义的变量称为全局变量
函数定义中的变量称为形式参数
需要注意的一点是,go语言可以定义同名的全局变量和局部变量,但是局部变量的优先级大于全局变量的优先级
package main
import (
"fmt"
)
var a int = 10
func main()
var a int = 20
fmt.Println(a)
Operation results:
20
数组
数组定义
package main
import (
"fmt"
)
func main()
var a [3]int //数组定义了未初始化
var b = [3]int1,2,3 //数组定义了按顺序初始化
var c = [3]int1:3,2:1 //数组定义了按索引初始化
var d = [3]int1,2:19 //数组定义了混合初始化(顺序和索引)
//可以使用编译器推导长度 var b = [...]int1,2,3
var i int
fmt.Println("Array output of A")
for i=0 ; i<3 ; i++
fmt.Println(a[i])
fmt.Println("Array output of B")
for i=0 ; i<3 ; i++
fmt.Println(b[i])
fmt.Println("Array output of C")
for i=0 ; i<3 ; i++
fmt.Println(c[i])
fmt.Println("Array output of D")
for i=0 ; i<3 ; i++
fmt.Println(d[i])
Operation results:
Array output of A
0
0
0
Array output of B
1
2
3
Array output of C
0
3
1
Array output of D
1
0
19
数组+函数+宏定义
似乎go语言没有宏定义这个概念,但是我觉得const关键字相当于C语言宏定义define 只是从使用上来看哦,底层原理应该是不一样的。
package main
import (
"fmt"
)
//Macro definition
const (Arraysize = 5)
//Func
func test(Array [Arraysize]int, Size int)int
i := 0
var ArrayTotal int = 0
for i=0;i<Size;i++
fmt.Println(Array[i])
ArrayTotal += Array[i]
return ArrayTotal
//Main
func main()
var Array = [Arraysize]int11,2,45,6,3
fmt.Println("Total array =",test(Array, Arraysize),"ok!")
Operation results:
11
2
45
6
3
Total array = 67 ok!
二维数组
package main
import "fmt"
func main()
var Array = [3][2]string
"北京", "上海",
"苏州", "无锡",
"广州", "深圳",
fmt.Println(Array)
//二维数组遍历
for _,v1 := range Array
for _,v2 := range v1
fmt.Println(v2)
Operation results:
[[北京 上海] [苏州 无锡] [广州 深圳]]
北京
上海
苏州
无锡
广州
深圳
指针
跟C语言一样,只需要记住指针也是个变量,跟int整形一样,只不过他是存放地址的变量
*在定义的时候只代表这是个几级指针,不代表取值
&是取地址
记清楚这两个符号,玩指针基本没问题
package main
import "fmt"
func main()
var a int = 10
var p *int = &a
fmt.Printf("Variable address: %x\\n", &a )
fmt.Printf("Variable address: %x\\n", p )
Operation results:
Variable address: c0000aa058
Variable address: c0000aa058
二级指针的使用
package main
import "fmt"
func main()
var a int = 10 //整形
var p1 *int = &a //一级指针
var p2 **int = &p1 //二级指针
fmt.Printf("Variable address: %x\\n", &a )
fmt.Printf("Variable address: %x\\n", p1 )
fmt.Printf("Variable address: %x\\n", &p1 )
fmt.Printf("Variable address: %x\\n", p2 )
fmt.Printf("Variable address: %x\\n", *p2 )
fmt.Printf("Variable content: %d\\n", a )
fmt.Printf("Variable content: %d\\n", *p1 )
fmt.Printf("Variable content: %d\\n", **p2 )
Operation results:
Variable address: c000012088
Variable address: c000012088
Variable address: c000006028
Variable address: c000006028
Variable address: c000012088
Variable content: 10
Variable content: 10
Variable content: 10
空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
一个指针变量通常缩写为 ptr
package main
import "fmt"
func main()
var p1 *int
fmt.Println(p1)
Operation results:
< nil >
指针数组
package main
import "fmt"
const MAX int = 3
func main()
a := []int10,100,200
var i int
var ptr [MAX]*int;
for i = 0; i < MAX; i++
ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
for i = 0; i < MAX; i++
fmt.Printf("a[%d] = %d\\n", i,*ptr[i] )
Operation results:
a[0] = 10
a[1] = 100
a[2] = 200
将指针传入函数进行值的交换
package main
import "fmt"
func exchange(p1 *int, p2 *int)int
*p1 , *p2 = *p2 , *p1
return 1
func main()
var a int = 10
var b int =2022
var p1 *int = &a
var p2 *int = &b
fmt.Println(*p1)
fmt.Println(*p2)
if exchange(p1, p2) == 1
fmt.Println("exchange ok!")
fmt.Println(*p1)
fmt.Println(*p2)
Operation results:
10
2022
exchange ok!
2022
10
结构体
结构体指针
package main
import "fmt"
type Human struct
name string
age int
func PutStructData(data *Human)
fmt.Println(data.name)
fmt.Println(data.age)
data.age = 98
func main()
var zhangsan Human
zhangsan.name = "zhangsan"
zhangsan.age = 21
PutStructData(&zhangsan)
fmt.Println("name:",zhangsan.name,"age:",zhangsan.age)
Operation results:
zhangsan
21
name: zhangsan age: 98
切片(Slice)
以上是关于go语言基础的主要内容,如果未能解决你的问题,请参考以下文章