go基础
go 语言基础
1 开发环境
1. go安装包
https://golang.google.cn/dl/
2. go的开发IDE
https://www.jetbrains.com
直接下一步,它会自动将go的环境添加到全局环境
注意:
-
goland创建项目,选择go 的安装路径(默认是自动选中)
-
gopath: 所有的代码必须放在这个路径下的src文件夹下,否则无法执行,默认创建到用户目录下的go文件夹,所有的系统都是一样的
-
取消掉 index entire gopath,否则默认将路径加到全局环境
-
路径和文件都不要出现中文
go的常用命令
go version
go env # go的环境变量
"""
set GO111MODULE= 空的,现在没有使用model模式
set GOPATH=C:\Users\小子\go 代码存放的路径
set GOROOT=E:\go go sdk安装的路径
"""
------------------------------------------------
go build # 编译型语言,需要先编译在执行,编译成可执行文件,执行可执行文件
go run #编译并执行,开发阶段用,两步并做一步
go get # 下载并安装依赖,相当于pip和npm
go fmt # 自动格式化代码
这些是需要记住的
2. 第一个hello,world!
vscode版本
# 1 写出go函数
package main // 声明包名, 包名是main 每一个文件都属于某一个包
import "fmt" // 导入包,内置包
func main() { // 定义一个main函数
fmt.Println("hello,world!!") // 打印函数==print()
}
// 单行注释
/*
多行注释
*/
# 2. 在控制台执行 go build
C:\Users\小子\go\src\day01>go build s1.go
# 3. 在控制台执行编译的go.exe
C:\Users\小子\go\src\day01>s1.exe
hello,world!!
# 或者 go run s1.go 编译并执行
go 的注释
// 单行注释
/*
多行注释
*/
goland版本:直接右键执行
入口
-
go 所有的编译型语言运行都要有一个入口
-
go的入口是main包下的main()函数
-
main包下不可以有多个main函数
-
当你创建多个go文件可以写main函数,因为设置的是以file执行,不是以项目来执行
3. 变量
3.1 定义变量的方式
方式一全定义:
- var 关键字 变量名 变量类型 = 变量值
- 在go中,变量定义了必须使用,如果不适应会报错
package main
import "fmt"
func main() {
// var 关键字 变量名 变量类型 = 变量值
var age int = 10 // 在go中,变量定义了必须使用,如果不适应会报错
fmt.Println(age)
}
方式二: 类型推导,类型不用写
package main
import "fmt"
func main() {
// 2 定义变量的第二种方式(类型推导,类型不用写)
var age = 10
var name = "lqz"
fmt.Println(name) // 打印并换行
fmt.Println(age) // 打印不换行
fmt.Printf("%T", age) // 查看变量类型
// 总结: 变量类型一旦确定,不能改变 变量不能重复使用
// 3 定义变量的第三种方式(简略声明,类型和var都不写)
a:=10
fmt.Println(a)
}
方式三: 类型推导,类型不用写
package main
import "fmt"
func main() {
// 3 定义变量的第三种方式(简略声明,类型和var都不写)
a:=10
fmt.Println(a)
}
3.2 声明多个变量
package main
import "fmt"
func main() {
var width, height = 100, 50 // 方式一
width, height := 100, 50 // 方式二
var (
name = "zzzz"
age = 29
height int
) // 方式三
fmt.Println(width, height)
}
小坑
var a int =10
//var b =99
b,a:=99,100 //这个不报错,我们觉得是重复定义,冒号左侧,只要有一个没有定义过的变量,就可以
fmt.Println(b)
fmt.Print(a)
总结:
-
变量类型在定义阶段一旦确定,不能改变
-
变量不能重复使用
3.3 变量命名规范
变量命名规范
-变量命令建议用驼峰,(大小写有特殊意义)
-go文件命名建议用 下划线
- 一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线
-大写字母和小写字母是不同的:Name和name是两个不同的变量
-关键字和保留字都不建议用作变量名
关键字
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
保留字
内建常量: 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
4 类型
整型:
- 有符号整形
-
int:在32位机器是int32,在64位机器是int64
-
int8:表示整数范围是:8个比特位,8个bit是1byte ,负数和0, 2的7次方-1 的范围
var a int8 =127 fmt.Println(a) a=127
-
int16 2的15次方减一
-
int32
-
int64
-
- 无符号整型
- uint8 2的8次方减一 定义一个人的年龄
- uint16
- uint32
- uint64
浮点型(小数),表示小数点后长度多少位
- float32
- float64
复数
-
complex64
-
complex128
-
byte:是int8的别名
var a byte = 'a' fmt.Println(a) a =97
-
rune:是int32的别名
var a rune = '你' fmt.Println(a) a = 20320 unicode编码
字符串
-
双引号包裹
package main import "fmt" func main() { s := "lqz is np" s1 := `lqz is np ` fmt.Println(s) fmt.Println(s1) }
-
反引号包裹 是声明格式返回的就是声明格式
package main import "fmt" func main() { s := "lqz is np" s1 := `lqz is np ` fmt.Println(s) fmt.Println(s1) }
结果:
lqz is np lqz is np
bool:就是True和False
默认的数字类型0是false 空字符串就false python所有的数据类型都带bool var a int64 var s string var b bool fmt.Println(a,b,s)
常量
package main import "fmt" func main() { //常量的定义 1 //const 变量名 变量类型 = 变量值 //const age int8 = 99 //fmt.Println(age) // ////类型推导 //const ages = 99 //fmt.Println(ages) //定义多个 const name, age = "zhangchen", 9 const ( names string = "laz" ages = 9 ) fmt.Println(name, age, names, ages) const ( s1 = iota s2 s3 s4 = 99 s5 =iota ) fmt.Println(s1) fmt.Println(s2) fmt.Println(s3) fmt.Println(s4) fmt.Println(s5) } # 结果 zhangchen 9 laz 9 0 1 2 99 4 const 关键字不能改变
函数
形式:
func名字(参数名 类型, 参数名 类型)(返回的类型,返回值类型){ 函数内容 return 返回值1, 返回值2 }
无返回值
package main import "fmt" func main() { //调用函数 add(2,3,"xxx") //这里的变量名不用写,直接填写数字,自动补齐 } //1. 有参数无返回值(定义函数) func add(a int, b int, msg string) { fmt.Println(a+b) fmt.Println(msg) } func add(a int, b int, msg string)可以简写成 add(a, b int, msg string)
**有参数,有多个返回值**
``` go
package main
import "fmt"
a,b := add(3,4)
fmt.Println(a,b)
a,_ := add(3,4) // 下划线忽略一个返回值
fmt.Println(a)
}
func add(a,b int) (int,int) { // 这里有几个返回值,就写几个数据类型
return a + b, a*b
}
命名返回值
package main
import "fmt"
func main() {
a,b:= add(3,4)
fmt.Println(a,b)
}
func add(a,b int)(c int,d int) {
c = a+b
d = a*b
return
} // 这里的return 返回的的c,d可以不用写,默认返回这个值
5 匿名函数
写在函数内部,函数不能有名字
package main
import "fmt"
func main() {
var a func()
a = func() {
fmt.Println("我是匿名函数")
}
a()
}
函数返回值为函数
package main
import "fmt"
func main() {
a := test()
fmt.Println(a) // 内存地址
a() //加括号调用
}
//函数返回值为函数
func test() func() {
return func() {
fmt.Println("我是匿名函数")
}
}
函数返回值为函数,返回的函数带参数 ,类型只要有不一样的地方,就不是一个类型
package main
import "fmt"
func main() {
a := test()
a("xxx")
}
// 函数返回值为函数,返回的函数带参数 ,类型只要有不一样的地方,就不是一个类型
func test() func(msg string) {
return func(msg string) {
fmt.Println(msg)
}
}
函数返回值为函数,返回的函数带参数,带返回值
package main
import "fmt"
func main() {
a := test()
fmt.Println(a(3,5))
}
//函数返回值为函数,返回的函数带参数,带返回值
func test() func(a,b int) int {
return func(a,b int) int {
return a+b
}
}
函数参数为函数类型,返回值为带参数,返回值的函数类型
package main
import "fmt"
func main() {
//a,b :=test(func() {
// fmt.Println("我是函数参数")
//})(3,4)
//
f := func() {fmt.Println("我是函数参数")}
f1 :=test(f)
a,b := f1(3,4)
fmt.Println(a,b)
}
// 函数参数为函数类型,返回值为带参数,返回值的函数类型
func test(f func()) func(a,b int) (int,int) {
f()
return func(a,b int) (int,int){
return a+b,a*b
}
}
闭包函数
go的闭包函数有一个内存逃逸
package main
import "fmt"
func main() {
// 闭包函数的使用
a := test(19) // a 是闭包函数
a()
//装饰器(go中没有装饰器的语法糖)通过闭包函数来实现装饰器
}
// 闭包函数 1 定义在函数内部,2 对外部作用域有引用 只是多了一个一种函数传参的方式
func test(age int) func() {
a := func() {
fmt.Println(age)
}
return a
}
给类型起别名
package main
import "fmt"
// 给类型起别名
type MyFunc func(a,b int) (int,string)
type Myint int
func main() {
var a int=10
var b Myint = 9
var a MyFunc =test()
c,d :=a(1,3)
fmt.Println(c,d)
}
func test() MyFunc{
return func(a, b int) (int, string) {
fmt.Println("xxx")
return 10,"ok"
}
}
6 作用域
package main
import "fmt"
//在同一个包下,函数名不能重名
//var a int //全局变量,全局有效,只要改了,就是改了
//func main() {
// fmt.Println(a) //0
// a=19
// fmt.Println(a) //19
// test1() //99
// fmt.Println(a) //99
//}
//
//func test1() {
// a=99
// fmt.Println(a)
//
//}
//变量的作用域范围
var a int //全局变量,全局有效,只要改了,就是改了
func main() {
var a int
fmt.Println(a) //0
a=19
fmt.Println(a) //19
test1() // 0
fmt.Println(a) //19
}
func test1() {
fmt.Println(a)
}