首页 > 技术文章 > Go

achai222 2020-10-21 22:38 原文

Go

1 Go简介

Go 即Golang,是Google公司2009年11月正式对外公开的一门编程语言。

Go是静态强类型语言,是区别于解析型语言的编译型语言(静态:类型固定 强类型:不同类型不允许直接运算)。

特点:

​ 跨平台的编译型语言

​ 语法接近C语言

​ 管道(channel),切片(slice),并发(routine)

​ 有垃圾回收的机制

​ 支持面向对象和面向过程的编程模式

2 Go下载安装

安装包下载地址为:https://golang.org/dl/。

如果打不开可以使用这个地址:https://golang.google.cn/dl/。

GO的代码必须放在GOPATH下的src文件夹内才能编译执行

// GOPATH的配置


/*
GOPATH:
代码存放路径,该目录下有三个文件夹(如果没有,要手动创建),
windows和mac默认在用户名下的go文件夹(GOPATH="/Users/liuqingzheng/go")

	-src——源码(包含第三方的和自己项目的)
	-bin——编译生成的可执行程序
	-pkg——编译时生成的对象文件
	
GOROOT:go开发工具包的安装路径,默认:C:\go

将GOROOT下的bin路径加入环境变量(默认已处理),这样任意位置敲 go 都能找到该命令
*/

//windows下修改在系统变量里添加
变量名:GOPATH
变量值:C:\>Go_Project

//mac和linux下修改
GOPATH="/Users/liuqingzheng/go/"  直接写要修改的路径即可

IDE可以使用Goland或vscode

3 Go命令

直接在终端中输入 go help 即可显示所有的 go 命令以及相应命令功能简介,主要有下面这些:

build: 编译包和依赖
clean: 移除对象文件(go clean :删除编译的可执行文件)
doc: 显示包或者符号的文档
env: 打印go的环境信息
bug: 启动错误报告
fix: 运行go tool fix
fmt: 运行gofmt进行格式化(go fmt :自动将代码格式)
generate: 从processing source生成go文件
get: 下载并安装包和依赖(go get github.com/astaxie/beego:下载beego框架)
install: 编译并安装包和依赖(go install 项目名:会将go编译,并放到bin路径下)
list: 列出包
run: 编译并运行go程序
test: 运行测试
tool: 运行go提供的工具
version: 显示go的版本
vet: 运行go tool vet

4 注释

// 单行注释

/*
多行注释
多行注释
多行注释
*/

5 启动入口

// 重点:
// go(所有编译型语言)项目要运行,必须有一个入口
// go的入口是main包下的main函数
// main包下可不可以有多个main函数:不可以



package main   //声明包名,包名是main,每一个go文件都属于某个包
import "fmt"    //导入包,内置包
func main() {   //定义了一个main函数,大括号包裹是函数体的内容
	fmt.Println("hello world") //打印函数等同与print()
}



// 启动方式:1.build+执行	2.run
// 编译
go build s1.go
// 执行
s1.exe

// 编译并执行
go run s1.go
// 在goland中,右键,运行即可

6 定义变量

// 三种定义方式
1 var age int =10
2 var age =10
3 age:=10
package main

func main() {
	//1 定义变量的第一种方式:全定义
	//var关键字 变量名 变量类型 = 变量值
	var age int =10   //在go中,变量定义了就必须使用,如果不使用就报错
	fmt.Println(age)

	//2 定义变量的第二种方式:类型推导(类型不需要写了)
	var age =10
	age=100
	var name ="lqz"
	fmt.Println(age)  //打印并换行
	fmt.Print(name)   //打印不换行
	fmt.Printf("%T\n",age)  //查看变量类型
	fmt.Printf("%T",name)
	fmt.Printf("%p",&name)

	//3 定义变量的第三种方式:简略声明(类型和var关键字都不写)这种用的多,冒号和等号是一家
	a:=10
	//var a int =100  //重复定义
	//var a =99    //重复定义
	a  :=                    99        //重复定义
	a=99
	fmt.Println(a)

	//4 其他变形方式
	//4.1  只定义不赋值
	var age int   //定义变量	//如果是只定义,不赋值,只能用这种
	var age      //只定义,不赋值,不行

	//4.2 声明多个变量
	var width, height int = 100, 50 // 声明多个变量
	var width,height =100,50      // 声明多个变量
	var width,height =100,"lqz"      // 声明多个变量
	width,height :=100,";qz"           // 声明多个变量

	//4.3 声明多个变量,并赋初值
	var (
		name   = "naveen"
		age  int  = 29
		height int
	)
	fmt.Println(name,age,height)


	//4.4 小坑
	var a int =10
	//var b =99
	b,a:=99,100    //这个不报错,我们觉得是重复定义,冒号左侧,只要有一个没有定义过的变量,就可以
	fmt.Println(b)
	fmt.Print(a)



	/*
		总结:
			1 变量类型在定义阶段就确定了,一旦确定,不允许改变
			2 变量不可以重复定义
			3 变量要先定义再使用
	*/
}

7 命名规范

/*
变量命名规范
	-变量命令建议用驼峰命名法(大小写有特殊意义)
	-go文件命名建议用下划线(蛇形命名法)
    - 一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线
    -大写字母和小写字母是不同的:Name和name是两个不同的变量
    -关键字和保留字都不建议用作变量名
*/



/*
Go语言中关键字有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

go语言中有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
*/

8 数据类型

/*
基础数据类型
数字:
	有符号整形
		-int:在32位机器是int32,在64位机器是int64
		-int8:表示整数范围是:8个比特位,8个bit是1byte ,负数和0, 2的7次方-1 的范围
		-int16 2的15次方减一
		-int32
		-int64
	无符号整型
		-uint8   2的8次方减一  定义一个人的年龄
		-uint16
		-uint32
		-uint64

	浮点型(小数),表示小数点后长度多少位
		-float32
		-float64
	复数
		-complex64
		-complex128
	byte:是int8的别名  单引号包裹
	rune:是int32的别名  单引号包裹
字符串
	双引号包裹
	反引号包裹  ` `


布尔
	bool true 和 false

数据类型默认值:
	数字类型是0
	字符串类型是 空字符串
	布尔类型   false

*/




/*
byte:int8
short :int16
int:int32
long:int64
float:float32
double:float64
*/

9 常量

常量的定义
第一种直接定义:
	const  变量名  变量类型 = 变量值
	const  age int8 = 99


第二种方式类型推导
    const age = 99
    age=88
    fmt.Println(age)

其他定义方式
    const name,age = "zhangsan",99
    const (
        name string ="lqz"
        age =99
    )



// 常量一修改就会报错!!!!

const (
	s1  =iota
	s2 =iota
	s3
	s4 =99
	s5 =iota
)
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
fmt.Println(s4)
fmt.Println(s5)



//const 关键字定义,不允许改变

10 函数

//定义方式

func 名字(参数名 类型,参数名 类型)(返回值类型,返回值类型){
	函数体内容
	return 返回值1,返回值2
}

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
	fmt.Println(a+int(b))



	//1 调用函数
	add(2,3,"xxx")
	var a int =add(2,3)
	a := add(2, 3)
	fmt.Println(a)
	//多返回值就需要用多变量接收
	a,b:=add(3,4)
	fmt.Println(a,b)
	//多返回值,忽略一个返回值
	a,_:=add(3,4)
	fmt.Println(a)
	fmt.Println(_)
	
	
	//匿名函数(定义在函数内部的函数,不能是有名函数),头等函数
	var a func()
	a = func (){
		fmt.Println("我是匿名函数")
	}
	a()
	//函数返回值是函数
	a:=test()
	fmt.Println(a)  // 函数内存地址
	a()
	//8 函数返回值为函数,返回的函数带参数
	a:=test()
	a("xxx")
	
	//9 函数返回值为函数,返回的函数带参数,带返回值
	var a func(a,b int)int
	a=test()
	fmt.Println(a(2,3))
	
	//10 函数参数为函数类型,返回值为带参数,带返回值的函数类型
	a,b:=test(func() {
		fmt.Println("我是函数参数")
	})(3,4)
	f:= func() {
		fmt.Println("我是函数参数")
	}
	
	f1:=test(f)
	a,b:=f1(3,4)
	fmt.Println(a,b)
	
	//闭包函数的使用
	a:=test(19)
	//a是闭包函数
	a()
	
	//装饰器是闭包函数的典型应用(go中没有装饰器的语法糖),通过闭包实现装饰器
	
	//类型重命名
	var a MyFunc =test()
	c,d:=a(1,2)
	fmt.Println(c,d)


}

//1 有参数无返回值(定义函数)
func add(a int,b int)  {
	fmt.Println(a+b)
}

//2 有参数无返回值,有多个相同类型参数
func add(a ,b int)  {
	fmt.Println(a+b)
}
//3 有参数无返回值,有多个相同类型参数,也有不同类型
func add(a ,b int,msg string)  {
	fmt.Println(a+b)
	fmt.Print(msg)
}

//4 多个参数,一个返回值
func add(a, b int) int {
	return a + b
}


//4 多个参数,多个返回值
func add(a, b int) (int,int) {
	return a + b,a*b
}

//5 命名返回值
func add(a, b int) (c int,d int) {
	c=a+b
	d=a*b
	//return时,不需要再写c,d了
	return
}


//6  函数是一等公民,函数可以赋值给变量

//7 函数返回值为函数
func test() func() {
	return func() {
		fmt.Println("我是返回函数")
	}
}

//8 函数返回值为函数,返回的函数带参数
//类型只要有不一样的地方,就不是一个类型
func test() func(msg string) {
	return func(msg string) {
		fmt.Println(msg)
	}
}

//9 函数返回值为函数,返回的函数带参数,带返回值
func test() func(a,b int) int{
	return func(a,b int) int {
		return a+b
	}
}

//10 函数参数为函数类型,返回值为带参数,带返回值的函数类型
func test(f func()) func(a,b int) (int,int){
	return func(a,b int) (int,int) {
		f()
		return a+b,a*b
	}
}

//11 闭包函数:1 定义在函数内部  2对外部作用域有引用
//闭包函数就是多了一种函数传参的方法,包进去了
func test(age int) func()  {
	a:= func() {
		fmt.Println(age)
	}
	return a
}

//12 重命名类型
func test()MyFunc  {
	return func(a,b int)(int,string) {
		fmt.Println("xxx")
		return 10,"ok"
	}

}

11 变量作用域

定义全局变量后,在局部未定义该变量的情况下可以直接修改全局变量的值
如果局部也定义了同名的变量,局部修改不会修改全局的变量
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)

}

推荐阅读