Go 基础语法
在Golang中,import导入的是目录,而不是包名。
在Golang的引用中,填写的是源文件所在的相对路径。
在代码中引用包内的成员时,使用包名而不是目录名。
项目在引用包的时候,会首先在GOROOT/src中寻找,例如fmt输入输出包,当无法找到的时候,会寻找PROJECT GOPATH/src,如果还是无法找到,将会寻找GLOBAL GOPATH/src。
// 初始化
var c, d float64
e, f := 9, 10
// 匿名变量
_, v, _ := getData()
func getData() (int, int, int) {
// 返回3个值
return 2, 4, 8
}
// 常量
const, no :=
// if
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
// for
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
// 对于相同类型的两个参数,参数类型可以只写一个
func add(x, y int) int {
return x + y
}
// Golang中的函数可以返回任意多个返回值
func swap(x, y string) (string, string) {
return y, x
}
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
// defer 语句会将函数推迟到外层函数返回之后执行, defer后面必须是函数调用语句
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
// 数组
var a [10]int
// 包括第一个元素,但排除最后一个元素
a[low : high]
// 切片
a := make([]int, 5) // len(a) = 5
b := make([]int, 0, 5) // len = 0, cap = 5
首字母小写:包内使用, private
首字母大写: 可以在包外被引入使用, public
指针:用&取地址,用*取地址中的值
Golang中的切片,不是拷贝,而是定义了新的指针,指向了原来数组所在的内存空间。修改了切片数组的值,也就相应的修改了原数组的值。 len (定义的长度), cap (内存的长度)
goroutine
go a()
go b()
go c()
通道的要点:
1.类似unix中管道(pipe),先进先出;
2.线程安全,多个goroutine同时访问,不需要加锁;
3.channel是有类型的,一个整数的channel只能存放整数。
消息的传递和获取必须成对出现,传数据用channel <- data,取数据用<- channel
使用range关键字,使用在channel上时,会自动等待channel的动作一直到channel被关闭。
select中会有case代码块,用于发送或接收数据。
用在有多个信道的情况
var ch0 chan int
var ch1 chan string
var ch2 chan map[string]string
type stu struct{}
var ch3 chan stu
var ch4 chan *stu
package main
import (
"fmt"
"time"
)
var ch chan int
func a() {
time.Sleep(3 * time.Second)
a := 5
ch <- a
fmt.Println("out of a")
}
func b() {
time.Sleep(1 * time.Second)
fromA := <- ch
b := fromA + 3
fmt.Println("b is ", b)
}
func main() {
ch = make(chan int, 1)
go a()
go b()
time.Sleep(20 * time.Second)
fmt.Println("out of main")
}
chSync := make(chan int) //无缓冲
chAsyn := make(chan int,1) //有缓冲
无缓冲场景:一直要等有别的协程通过<-chSync接手了这个参数,那么chSync<-1才会继续下去,要不然就一直阻塞着。
有缓冲场景:chAsyn<-1则不会阻塞,因为缓冲大小是1,只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。
type Shape interface {
Area() float64
Perimeter() float64
}
type Rect struct {
height float64
weight float64
}
func (p *Rect) Area() float64 {
return p.height * p.height
}
func (p *Rect) Perimeter() float64 {
return 2* (p.height + p.height)
}
func main() {
var s Shape = &Rect{height:10, weight:8}
fmt.Println(s.Area())
fmt.Println(s.Perimeter())
}
// go convey
package main
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestRect(t *testing.T) {
convey.Convey("TestRect", t, func() {
var s Shape = &Rect{height: 10, weight: 8}
convey.So(s.Area(), convey.ShouldEqual, 80)
convey.So(s.Perimeter(), convey.ShouldEqual, 30)
})
}
// http gin框架
package main
import (
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func SayHello(c *gin.Context) {
c.String(http.StatusOK, "hello") //以字符串"hello"作为返回包
}
func main() {
engine := gin.Default() //生成一个默认的gin引擎
engine.Handle(http.MethodGet,"/say_hello", SayHello)
err := engine.Run(":8080") //使用8080端口号,开启一个web服务
if err != nil {
log.Print("engine run err: ", err.Error())
return
}
}
// 结构体
type 结构体名 struct {
字段1 类型
字段2 类型
}
// 第一种: 返回该实例的结构类型
var s T
s.a = 1
s.b = 2
// 第二种:返回指针
ming := new(people)
ming.name = "xiao ming"
ming.age = 18
// 第三种:返回指针
ming := &people{"xiao ming", 18}
// 第二种,第三种声明形式
(*ming).name = "xiao wang"
// 方法
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
只有指针接收者类型的方法,才能修改这个接收器的成员值,非指针接收者,方法修改的只是这个传入的指针接收者的一个拷贝。
// slice
var arr = [...]int{1,2,3,4}
fmt.Println(arr) //[1,2,3,4]
slice := arr[:]
fmt.Println(slice) //[1,2,3,4]
slice = append(slice,[]int{5,6,7}...) //此时slice的引用地址已经发生改变了,它引用的底层数组再也不是arr了,而是一个新的数组newarr[1,2,3,4,5,6,7]
// 数组初始化
arr := [10]int{} 或 var arr [10]int
Go 语言中的数组是值类型,一个数组变量就表示着整个数组,意味着 Go 语言的数组在传递的时候,传递的是原数组的拷贝
s := []int{1, 2, 3} 简短的赋值语句
var s []int var 申明
make([]int, 3, 8) 或 make([]int, 3) make 内置方法创建
s := ss[:5] 从切片或者数组创建
// 创建
// map[KeyType]ValueType
var m map[int]int
m := make(map[int]int)
m := map[int]int{
1: 1,
2: 2,
}
// 读取
i := m[1]
v, ok := m[1]
// 遍历
for key, value := range m {
println("Key: ", key, "Value: ", value)
}
// 删除
delete(m, 1)