1-5 目录结构
“包”在go文件第一行进行指定。
如果两个go文件都属于main包,可以直接调用。
例如,两个go文件都属于main包,test.go和main.go
要用 `go run test.go main.go`命令,因为main包默认不会加载其他文件
1-6:go的基本命令
- `go run src/github.com/xx/hello.go` //原理也是先编译再运行
- `go build -o bin/hello.exe github.com/xx/hello`
- `go install github.com/xx/hello` //安装可执行文件到bin目录下,要配置 "GOBIN" 环境变量
- `go test` //执行单元测试或压力测试
- `go env` //go环境变量,GOPATH是环境变量
- `go fmt github.com/xx/hello.go` //格式化源代码
- 单行注释 //
- 多行注释 /* */
1-7:go语言特性
- 垃圾回收
- 内存自动回收,再也不需要开发人员管理内存
- 开发人员专注业务实现,降低心智负担
- 只需要new分配内存,不需要释放
- 天然并发
- 从语言层面支持并发,非常简单。只需要go一下(go是启动线程吗??不知道)
- goroutine,轻量级线程,创建成千上万个goroute称为可能
- 基于CSP(通讯序列进程)模型实现
package main
import ("fmt""time")
func cal(){fmt.Println("开始进行大量计算...")time.Sleep(time.Second*2)}
func main(){go cal()fmt.Println("主线程完成")time.Sleep(time.Second * 3)}
- channel
- 管道,类似unix/linux中的pipe
- 多个goroute直接通过channel进行通信
- 定义全局pipe进行通信
-
package main
import("fmt")
var pipe chan int //定义全局pipe进行goroute通信,如果全局定义了多个pipe会分不清,不建议用全局的pipe进行通信
func add(a int, b int) int {sum := a + bpipe <- sum //结果扔进管道return sum}
func main() {pipe = make(chan int, 1)go add(2, 5)sum := <- pipe //阻塞,管道有值才返回fmt.Println("sum=", sum)} - pipe传参进行通信
package main
import("fmt")
func add(a int, b int, p chan int) int {sum := a + bp <- sum //结果扔进管道return sum}
func main() {pipe := make(chan int, 1)go add(2, 5, pipe)sum := <- pipe //阻塞,管道有值才返回fmt.Println("sum=", sum)}
- 支持任何类型(字符整数类都可以放进管道)
package main
import("fmt")
func testPipe() {pipe := make(chan int, 3) //定义管道,管道长度3,存放int,管道是队列的数据结构pipe <- 1 // 向管道中放数据pipe <- 2pipe <- 3fmt.Printf("取出前:%d", len(pipe)) // 3//从管道取出放入变量a中a := <- pipefmt.Printf("取出:%d",a) // 1fmt.Printf("取出后:%d", len(pipe)) // 2}
- 多返回值
- 一个函数返回多个值
package main
import ("fmt")
func cal(a int, b int) (int, int) {return a + b, a -b}
func main(){a, b := cal(4, 5)x, _ := cal(5, 6) // 如果只想用第一个数据,就用_忽略第二个fmt.Printf("a=%d, b=%d", a, b)}
- 编译型语言
- 性能只比c底10%
- 效率和python,PHP差不多
1-9 变量
- 定义变量
var a int
var b string
var c bool
var d int = 8
var e string = "hello"等价于
var(
a int
b string
c bool
d int = 8
e string = "hello"
)
- 格式化输出
var a int
var b bool
var c string
var d float32
fmt.Printf( "%d, %t, %s, %f" ,a ,b, c, d) //注意:不是Println,必须是Printf
1-10 常量
- 常量必须要赋值。 定义常量时,不写类型,go会进行推导
const b string="hello"
const b = "hello"
const Pi = 3.1415926
const a = 9/2或者
const (
a int = 100
b string = "hello"
)
- 定义常量时某行不写,和上一行一样
const (
a = iota //iota默认值是0,后面b,c会自增变为1,2
b //不写默认为b=iota
c
)
const (
a = 1 << iota // 1 左移0位 = 1
b // b = 1 << iota 1左移1位=2
c // 1左移2位 = 4
)
1-11常量练习
const (
A=iota
B
C
D = 8
E
F = iota
G
)const (
A1 = iota
A2
)
ABCDEFG是多少?
A=0, B=1, C=2, D=8, E=8, F=5, G=6
A1=0, A2=1
总结: 1.iota在const()内生效 2.iota隔一行新增1
1-12 数据类型
- 布尔类型
var b bool
var b bool=true
var b = false //布尔类型没有赋值默认为false
等于 == 、 不等于 != 、 取反 !b 、 &&逻辑与(前面为假不执行后面) 、 || 逻辑或(前面为真不执行后面) 、
格式化输出占位符:%t
- 整数和浮点数
- int8、int16、int32、int64 (整型,可正可负,后面的数字是二进制位)
- unit8、unit16、unit32、unit64 (无符号整数,只能存正数)
- int和unit,和操作系统平台相关 (32位平台占4字节,64位平台占8字节)
- float32和float64浮点类型
- 所有整数初始化为0,所有浮点数初始化为0.0,布尔类型初始化为false
说明:
- Go是强类型语言,不同类型相加以及赋值是不允许的
- 那怎样才能实现不同类型相加呢? 要强转 int(a)
- 输出占位符,整数%d 十六进制%x 浮点数%f
字符类型
字符是单个字符,用单引号,字符串用双引号,字符ASCII编码的
package main
import("fmt")
func main() {var b byte = 'a'fmt.Println(b) // 97fmt.Printf("%c", b) // a}
1-13 数据类型-字符串
var str string
var str string = "hello world"
- 字符串占位符 %s
- 万能输出占位符%v 不知道用什么占位符可以用%v
- c := "hello" 语句 , 用 := 的方式。省略了var string c 的过程
- 字符串两种表示方式:双引号"xxx" 反引号`xx`里面全转义
字符串常用操作
- 长度:len(str)
- 拼接:+, fmt.Sprintf("%s%s", string1, string2)
- 分割:strings.Split(string1, ";") // package "strings" 返回数组
- 包含:strings.Contains("xx")
- 前缀或后缀判断:strings.HasPrefix("xx.com","xx"), strings.HasSuffix("ff.yy","yy")
- 子串出现的位置:从前往后strings.Index(string1, "xx"), 从后往前strings.LastIndex(string1, "xx")
- join操作:strings.Join(a[]string, sep string)
var strArr []string = []string{"aa", "bb", "cc"}
resultStr := strings.Join(strArr, ";")
fmt.Printf("result=%s\n", resultStr) //aa;bb;cc
报错,编译型语言要把操作放在函数里才行。
全局只能进行声明和初始化, var a int = 1 这种是编译的时候初始化, a := 1这种是执行的时候初始化