本文阅读课程来源见此go系列教程
//声明方式一
//var name type
var age int
age = 25
//声明并初始化
var age int = 25
//让go类型推断
var age = 25
//声明多个变量,注意变量不能重复定义
var width, heigth int = 210, 220
//简短声明
age := 25
//简短声明多变量,
age, name := 25,"wengwei"
//注意多变量声明不能完全重复
age, name := 25,"wengwei"
age, name := 26,"wengwei"
//上面定义会报错
age, name := 25,"wengwei"
age, name2 := 26,"wengwei"
//上面定义不会报错
go支持一下几类基本类型
注意go语言是强类型语言,不同类型之间不能运算,需要转换,转换方法T(v),将v转换为T类型的数据。
go语言常量声明如下
const hello = "Hello,World!"
const age int = 14
需要注意的是,常量在赋值之后便不能再被改变,试图再次赋值会报错。
函数声明如下
func funcName(param type) returntype{
}
func funcName(param type) (returntype1,returntype2){
}
func funcName(param type) (return1,return2 returntype){
//函数体内可以使用return1变量和return2变量
//可以直接return,则返回return1和return2
return
}
_ 在 Go 中被用作空白符,可以用作表示任何类型的任何值。以此通常使用_作为不使用的返回值代理。
属于某一个包的源文件都应该放置于一个单独命名的文件夹里。按照 Go 的惯例,应该用包名命名该文件夹。
package xxxx
import "xxx"
包的初始化顺序
具体对应流程
import "fmt" //最常用的一种形式
import "./test" //导入同一目录下test包中的内容
import f "fmt" //导入fmt,并给他启别名f
import . "fmt" //将fmt启用别名".",这样就可以直接使用其内容,而不用再添加fmt,如fmt.Println可以直接写成Println
import _ "fmt" //表示不使用该包,而是只是使用该包的init函数,并不显示的使用该包的其他内容。注意:这种形式的import,当import时就执行了fmt包中的init函数,而不能够使用该包的其他函数。
if condition {
} else if condition{
} else {
}
if statement;condition{
}
一个注意点
else 语句应该在 if 语句的大括号 } 之后的同一行中。如果不是,编译器会不通过。
for no, i := 10, 1; i <= 10 && no <= 19; i, no = i+1, no+1 {
fmt.Printf("%d * %d = %d\n", no, i, no*i)
}
func main(){
finger := 4
//注意这里的;
switch f := funx();{
case 1:
fmt.Println("thumb")
case 2:
fmt.Println("2")
case 3,4,5:
fmt.Println("other")
default:
fmt.Println("def")
}
}
注意点
切片初始化时是引用对应的数组或切片底层的数组的,因此,改变切片会影响原来的数组,要想不影响就需要
func find(num int, nums ...int) {
//code
}
//直接调用
find(90,90,91,92)
//切片传入方法
nums := []int{ 11,12,13 }
find(11,nums...)
len([]rune(s))
package main
import (
"fmt"
)
type Employee struct {
firstName, lastName string
age, salary int
}
func main() {
//creating structure using field names
emp1 := Employee{
firstName: "Sam",
age: 25,
salary: 500,
lastName: "Anderson",
}
//creating structure without using field names
emp2 := Employee{"Thomas", "Paul", 29, 800}
//匿名结构体
emp3 := struct {
firstName, lastName string
age, salary int
}{
firstName: "Andreah",
lastName: "Nikola",
age: 31,
salary: 5000,
}
fmt.Println("Employee 1", emp1)
fmt.Println("Employee 2", emp2)
fmt.Println("Employee 3", emp3)
}
类型断言语法
//v为接口类型,T为抽象或具体类型
v.(T)
//如果无法实现断言,v会返回T的零值
v, ok := v1.(T)
断言的规则
type I interface {
M()
}
type T1 struct{}
func (T1) M() {}
type T2 struct{}
func (T2) M() {}
func main() {
var v1 I = T1{}
//如果无法实现断言,v2会返回T2的零值
v2, ok := v1.(T2)
if !ok {
fmt.Printf("ok: %v\n", ok) // ok: false
fmt.Printf("%v, %T\n", v2, v2) // {}, main.T2
}
}
type I1 interface {
M1()
}
type T1 struct{}
func (T1) M1() {}
type I2 interface {
I1
M2()
}
type T2 struct{}
func (T2) M1() {}
func (T2) M2() {}
type T3 struct{}
func main() {
var v I1
switch aux := 1; v.(type) {
case T1:
fmt.Println("T1")
case T2,T3:
fmt.Println("T2")
case nil:
fmt.Println("nil",aux)
default:
fmt.Println("default",aux)
}
}
//需要带上xxx.go不然提示找不到模块
go test xxx_test.go xxx.go
//查看覆盖率
go test -cover
//产生html查看
go test -coverprofile=xxx.out
go tool cover -html=xxx.out
go中控制并发的两种经典模式,一个是WaitGroup,一个是Context。
Context接口并不需要我们实现,Go内置已经帮我们实现了2个,我们代码中最开始都是以这两个内置的作为最顶层的partent context,衍生出更多的子Context。
一个是Background,主要用于main函数、初始化以及测试代码中,作为Context这个树结构的最顶层的Context,也就是根Context。
一个是TODO,它目前还不知道具体的使用场景,如果我们不知道该使用什么Context的时候,可以使用这个。
var key string="name"
func main() {
ctx, cancel := context.WithCancel(context.Background())
//附加值
valueCtx:=context.WithValue(ctx,key,"【监控1】")
go watch(valueCtx)
time.Sleep(10 * time.Second)
fmt.Println("可以了,通知监控停止")
cancel()
//为了检测监控过是否停止,如果没有监控输出,就表示停止了
time.Sleep(5 * time.Second)
}
func watch(ctx context.Context) {
for {
select {
case <-ctx.Done():
//取出值
fmt.Println(ctx.Value(key),"监控退出,停止了...")
return
default:
//取出值
fmt.Println(ctx.Value(key),"goroutine监控中...")
time.Sleep(2 * time.Second)
}
}
}
所谓的闭包是指内层函数引用了外层函数的变量或引用了自由变量的函数,其返回值也是一个函数。
本节内容来源
func outer(x int) func(int) int{
return func(y int) int{
return x+y
}
}
func main() {
s := []string{"a","b","c"}
for _,v := range s{
go func(){
fmt.Println(v)
}()
}
select {} //阻塞模式
}
//输出结果
// c
// c
// c
// 原因,没有将v值传入闭包,导致闭包只能获取最后一次循环的值
func test() []func() {
var s []func()
for i:= 0;i<3;i++ {
s = append(s,func(){
fmt.Println(&i,i)
})
}
return s
}
// 每次append后的函数没有执行,并且引用的变量都是i,随着i的增加,最后读取的i都是3
//这里存储的函数,只有i=3的情况,因为i不是参数导入的,需要i的不同,可以将i拷贝
func test() []func() {
var s []func()
for i:= 0;i<3;i++ {
x := i
s = append(s,func(){
fmt.Println(&x,x)
})
}
return s
}
func main() {
x, y := 1, 2
defer func(a int) {
fmt.Printf("x:%d,y:%d\n", a, y) // y 为闭包引用
}(x) // 复制 x 的值
x += 100
y += 100
fmt.Println(x, y)
}
//结果
// 101,102
// x:1,y:102
type A int
type A=int
原文:https://www.cnblogs.com/weiweng/p/12497260.html