GO
安装-vscode
- 下载
- 控制台
go version
查看是否安装成功
- 控制台
- vscode 中使用
- step1: 在控制台中输入以下命令
go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct
- step2: vscode 中安装插件 go
- step3: vscode 中按下
ctrl+shift+p
把七个依赖全部勾选后点击ok下载
- 使用
- 在文件->打开文件夹打开我们的$GOPATH下的src目录 建工程写代码
- 在终端中用go build xx和go run xx来运行代码 或者 VSCode的插件模块,搜索code running来安装插件
安装-idea
- idea 下载
- idea 安装 go 插件
- 在 idea 的 plugin 的应用市场如果下载若失败则看下面方法
- 在线插件 找到自己想要的插件,可以下载到本地然后再 idea 的 plugin 中选择从本地导入即可
- 推荐插件
- translation
基础知识
// 会把换行符转化为分号,以下是特例
func main { // 不会转化
}
func main // 错误的书写方法
{
}
var a = 1+2;
var a = 1 // 会转化
+2;
var a = 1+ // 不会转化
2;
包
-
go get golang.org/x/tools/cmd/goimports 自动删除\添加包
-
程序导入了两个包,用括号把它们括起来写成列表形式, 而没有分开写成独立的import声明。两种形式都合法,列表形式习惯上用得多。包导入顺序并不重要;gofmt工具格式化时按照字母顺序对包名排序。
import ( "fmt" "os", "bufio" ) fmt.Sprintf(); fmt.Println(); // %t 布尔:true或false; %q 带双引号的字符串"abc"或带单引号的字符'c'; %T 变量类型 input:=bufio.NewScanner(os.stdin); input.Scan(); // 每次调用都会读取一行 input.Text();
-
每个 Go 应用程序都包含一个名为 main 的包。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)
info
-
学习文档
-
当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )。
-
表达式(Expression)有值,而语句(Statement)不总有。
-
自增语句i++给i加1;这和i += 1以及i = i + 1都是等价的。对应的还有i–给i减1。它们是语句,而不像C系的其它语言那样是表达式。所以j = i++非法,而且++和–都只能放在变量名后面,因此–i也非法。a = a++ // 这是不允许的,会出现编译错误
-
for 循环
for { // 无限循环
// ...
}
// 不可重复声明变量
var a = 1;
var a int = 1;
a:=1;
intVal := 1
// 相当于
var intVal int = 1;
f := 'hi'
// 相当于
var f string = 'hi';
var ( // 这种因式分解关键字的写法一般用于声明全局变量
a int
b bool
)
//这种不带声明格式的只能在函数体中出现
//g, h := 123, "hello"
// 如果你在定义变量 a 之前使用它,则会得到编译错误 undefined: a。声明了缺不使用也是不行的,但是全局变量是允许声明但不使用的
// iota 是编辑器可以修改的常量,每 const 出现时就会被初始化为 0,随着标识符数量增加而增加
const (
i = iota
j = iota
x = iota
)
const xx = iota
const yy = iota
func main(){
println(i, j, x, xx, yy) // 输出是 0 1 2 0 0
}
var b int = 5
var ptr1 *int = &b;
fmt.Println(*ptr1)//5
fmt.Println(ptr1)// b 的地址
var numbers [3]int
var numbers = [...]int{1, 2, 3, 4, 5}
numbers:=[5]int{1:2,2:19}
animals := [][]string{}
// 创建三一维数组,各数组长度不同
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// 使用 append() 函数将一维数组添加到二维数组中
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
- 局部变量:在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。
- 全局变量:在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。有异议
- 可通过花括号来控制变量的作用域
- 在Go语言中,字符串类型是一个结构体,包含一个指向底层数据的指针和一个表示字符串长度的整数。在64位系统上,每个指针占用8字节,整数占用8字节。因此,一个字符串类型在64位系统上总共占用16字节的空间。对于给定的代码a = “hello”,虽然a是一个字符串类型的变量,但在赋值时,实际上是将一个指向字符串"hello"底层数据的指针赋值给了a。因此,unsafe.Sizeof(a)返回的是一个指针的大小,即8字节。因此,代码
a = "hello"; unsafe.Sizeof(a)
的运行结果是8。 &a;
将给出变量的实际地址。- Go 没有三目运算符,所以不支持 ?: 形式的条件判断。
- Go 函数可以返回多个值
- 未定义长度的数组(切片)只能传给不限制数组长度的函数,定义了长度的数组只能传给长度一样的函数。
- select 语法 (不懂)
- 对于底层数组容量是 k 的切片 slice[i:j] 来说新的切片 长度: j-i 容量: k-i
- 在做函数调用时,slice 按引用传递,array 按值传递
- 并发 (不懂)
// 结构体
type Person struct {
name string,
age int,
}
// one
Person{'hi', 10};
// two
Person{name:'hi', age:10};
// three
var p1 Person;
p1.name = 'hi';
// 切片和range
var slice1 []type = make([]type,10);
slice2:=make([]type,10,20);
len(slice2)//10
cap(slice2)//20
var slice3 []int // console.log(slice3) nil
append(slice3, 1,2,3) [1,2,3]
copy(slice1,slice2)
// range也可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
for i, v := range slice3 {
fmt.Printf("2**%d = %d\n", i, v)
}
// map
var map1 = make(map[string]int, 10) // 创建一个初始容量为 10 的关键字为 string 类型,值为 int 类型的 map; 遍历 Map 时返回的键值对的顺序是不确定的
map2 = map([string]string) { // := 写错啦
name: '张三',
age: '10'
}
keyValue:=map2['name']
key,value:=map2['age']
map2['age'] = '20'
delete map2['name']
for key:=range map2 {
}
// 数据类型转化, go 中没有隐式转化
value := float64(12)
value, err := strconv.Atoi('123')
value, err := strconv.Itoa(123)
value, err := strconv.ParseFloat('12', 64)
value, err := strconv.FormatFloat(12.345, 'f', 2, 64)
// 接口 不熟悉
type If interface {
run() string
}
type Person struct {
name string
}
func (p Person) run() string {
//
return p.name
}
var p If = Person{'张三'}
p.run() // 张三
// 通道
ch := make(chan int);
value,ok:=<-ch // 当收不到数据的时候 ok 就变成了 false,
close(ch) // 关闭通道
ch2 := make(chan int, 100)
// 如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。