go语言入门
go简介
go语言,golang,是谷歌公司开发的,是编译型语言。
编译型语言,需要将go代码编译成可执行文件,然后就可以在相应的系统上跑了,而开发环境中,我们需要下载go sdk,这个是go管理代码资源的工具,我们可以通过go build命令来编译go代码,go run来编译+运行go代码(编译的代码即用即删)。
hello world
package main // 声明这个go文件属于哪个包,main有特殊含义
// 一个项目要运行必须要有main包,运行的入口是main包下的main函数
// 包导入,不使用,会报错,编译不过,导入后必须要使用
import "fmt"
// func 定义一个函数 ,main 是主函数,没有参数,没有返回值,整个项目入口
func main() {
// 在控制台输出hello world
fmt.Println("hello world")
}
如果实在goland里面运行,那么可以用比较快捷的方式,直接右击文件编译运行。不过一般来说,go的结构会基于包,一个项目里只有一个main包,程序的入口也就是这个main包下的main函数。
我们学习代码可以采取单个go文件编译执行。
在上述的hello world程序中,go语言会要求程序导入的包必须使用,否则编译报错,这样实际上可以节约我们不必要的内存和效率开支,不引用的包就应该不导入。goland编辑器编辑时,针对这一点,做了一些处理,我引用到包时,它会自动帮我在顶部导入,在我代码中删除对这个包的引用时,它也会检测到并把导入那一句代码给删掉,提升了开发的效率。
变量命名规范
规则
可以由字母(unicode)、下划线、数字组成,不能由数字开头,区分大小写,关键字和保留字不推荐作为变量名
25个关键字:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
37个保留字:
内置常量: true false iota nil
内置类型: int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error
内置函数: make len cap new append copy close delete
complex real imag
panic recover
规范
go的命名习惯是:变量、函数名用小驼峰,文件名用下划线格式
对比python:全下划线
对比java:全驼峰
变量声明
注意:go中的变量被声明后,必须被使用,否则会编译报错,所以goland编辑器有时会飘红提示,我们需要后文使用变量后飘红提示才会消失。
三种基本的声明语法:
// 完全定义 var关键字 变量名 变量类型 = 变量值
var name string = "leethon" // go的字符串必须是双引号
// 类型推导 var关键字 变量名 = 变量值 (根据变量名确认这个变量的类型)
var name = "leethon" // 变量声明后,其数据类型不会再变了,因为go是静态语言
// 简短声明 变量名 := 变量值 (省略了var关键字)
name := "leethon"
一次性声明多个变量:
// 完整定义多个变量
var name, age, hobby string = "leethon", "19", "篮球" // 完整定义则类型指定必须一致
var (
name string = "leethon"
age int = 19 // 这种写法可以单独声明变量类型
hobby = "篮球" // 也可以不指定类型,让其自己推导
)
// 类型推导
var name, age, hobby = "leethon", 19, "basketball" // 类型推导的多个变量类型可不一致
// 简略声明
name, age, hobby := "leethon", 19, "basketball"
变量也可以先声明后赋值,如果采取这种方式,则必须使用完整定义的语法,且实际上被声明的变量会有其类型的默认值
var name string // 默认为空字符串
var age int // 默认值为0
数据类型
查看变量的类型,%T
是占位符,最终会将变量的类型放入字符串
fmt.Printf("a的值是:%v,类型是:%T", a, a)
数字类型
// 整型
int8 只占8bit,可以表示 -128~127 的数字范围
int16 占两个字节 可以表示 -2^15~2^15-1的数字
int32 int64 依次类推
int 32位机器是 int32 ,64位机器是 int64
// 无符号整型(只表示自然数)
uint8 只占8bit,可以表示 0~255 的数字范围
uint16 占两个字节 可以表示 0~2^16-1的数字
uint32 uint64 依次类推
uint 32位机器是 uint32 ,64位机器是 uint64
// 浮点型:表示小数
float32 float64
// 复数类型:实部和虚部
complex64 complex128
// rune byte
byte 是 uint8 的别名
rune 是 int32 的别名
字符类型
// string
"lee" "hello world" 这些都是字符串,不能用单引号包裹
`反引号包裹
可以写多行的字符串`
// 单引号
'c' '7' '好' 使用单引号包裹的不是字符串类型,它对应字符编码的整型数字
var a, b, c = 'a', '2', '三'
fmt.Printf("%T %v,%T %v,%T %v", a, a, b, b, c, c)
// int32 97,int32 50,int32 19977
布尔类型
true false
常量
go中,常量用关键字const进行声明,常量一经声明,不能再更改它的值
// 完整定义
const 常量名 数据类型 = 数据值
// 类型推导
const 常量名 = 数据值
// 定义多个
const (
male = 1
female = 2
unknown = 0
)
// 依赖规则,如果下方常量声明时不赋值,那么和上方常量保持一致
const (
a = 10
b // 10
)
iota
iota是一个特殊常量,是一个可以被编译器修改的常量,我们在代码层面不会修改,而在编译过程中会根据一定的规则变化。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
iota经常用作枚举值:
const (
unknown = iota // 0
male // 1
female // 2
)
iota结合上文提到的依赖规则,在声明多个常量时,可能会出现以下情况:
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
)
// iota递增,且中途有其他常量不使用其值也不影响,重新出现iota时再重新引用
我们还可以结合位运算做一些有趣的枚举:
const (
KB = 1<<(iota * 10) // 1左移10位
MB // 1左移20位
GB
)
函数
主函数main
main函数是程序的入口,也可以说是工程的主体,每一个go程序必须有一个main函数才能运行,main函数没有参数,也没有返回值。
函数定义与调用
// 定义无参函数
func test() {
fmt.Println("无参函数")
}
// 定义有参函数,括号里面放入形参,必须指定参数类型
func test1(a int, b string) {
fmt.Println(a)
fmt.Println(b)
}
// 如果参数类型一致的变量,则可以简写
func test2(a, b int, c string){
fmt.Println(a, b, c)
}
// 定义有返回值的函数,括号后面需要指定返回值的数据类型
func test3(a, b int) int {
return a + b
}
// 一个函数可以有多个返回值,多个返回值都要指定数据类型,格式如下
func test4(a, b int) (int, int) {
return b, a
}
// 函数可以在很多地方调用,主函数和函数中都可以对其他或自己进行调用
func main(){
test() // 调用无参函数
test1(11, "leethon") // 调用有参函数,数据类型和位置必须相对应
var a int = test3(1, 2) // 调用有参函数,且接收返回值
fmt.Println(a)
b, c := test4(3, 4) // 必须有相应个数的变量去接收返回值
fmt.Println(b, c)
b, d :=test4(b, c) // :=前面只要有未声明的变量即可,也可含声明过的变量
fmt.Println(b, c, d)
b, c = test4(b, c) // =就是单纯的赋值符号,b和c已在前文定义
fmt.Println(b, c)
// 总结,可以直接定义变量去接收返回值,也可以用声明过的变量去接收,重点是变量与返回值的个数对应上
_, c = test4(1, 2) // _表示忽略该位置的返回值,在go中_不能当做变量使用
}
匿名函数
// 定义匿名函数
func() {}
// 定义传参和有返回值的匿名函数
func(a int) string{
return "ok"
}
// 匿名函数定义完直接调用(虽然没用,但是支持这么做)
func(){
fmt.Println("立即执行!")
}()
函数是一等公民
匿名函数没有名字,但是它可以被赋值给变量,也可以传参,实际上函数在go语言中属于一等公民。
所谓一等公民,是指支持所有操作的实体, 这些操作通常包括作为参数传递,从函数返回,修改并分配给变量等。
///// 来看看一等公民意味着什么
// 1.直接将匿名变有(分配给变量)
f := func(){
fmt.Println("我有名了!")
}
// 验证f变量的数据类型
fmt.Printf("%T", f) // func()
// 2.当参数传入
// 定义一个需要函数当形参的函数:
func test(f func()){
f() // 调用传入的函数实参
}
// 3.函数的形参和返回值类型都是函数类型的一部分
也就是说函数类型不只有 func()
还有 func(int) int / func(int string) / func(string)(int int) 等等,所以函数类型也是很复杂的
// 4.闭包函数,装饰器也是可以实现的
func outer(f func()) func(){ // 这里实际上就表名了能装饰的函数类型只有无参函数,且结果为无参函数
inner := func(){
f() // 局部作用域引用外部作用域的变量,就叫闭包
fmt.Println("加点额外的东西")
}
return inner // 装饰器
}
变量空间作用域
作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
Go 语言中变量可以在三个地方声明:
- 局部变量:函数内定义的变量称为局部变量
- 全局变量:函数外定义的变量称为全局变量
- 形式参数:函数定义中的变量称为形式参数
局部变量:
package main
func main(){
var a int = 10
b := a + 20
// a 和 b 都是局部变量
}
全局变量:
package main
import "fmt"
var a int = 10 // a是全局变量,任何函数中都可以对其进行引用
func main(){
fmt.Println("main", a) // main 10
test()
fmt.Println("main", a) // main 10
}
func test(){
a := 20 // 局部如果重新声明a,则在函数中,这个a使用的是局部的,且不会影响全局
fmt.Println("test", a) // test 20
}
形式参数:
package main
import "fmt"
func main() {
/* main 函数中声明局部变量 */
var a int = 10
var b int = 20
var c int
c = sum(a, b);
fmt.Printf("main()函数中 c = %d\n", c);
}
/* 函数定义-两数相加 */
func sum(a, b int) int {
fmt.Printf("sum() 函数中 a = %d\n", a);
fmt.Printf("sum() 函数中 b = %d\n", b);
// var a = 10 这种方式是错的,形式参数不能再被重复声明
return a + b;
}
标签:语言,函数,int,fmt,func,go,main,入门
From: https://www.cnblogs.com/Leethon-lizhilog/p/17353289.html