下载(尽量下载压缩包的zip):https://golang.google.cn/dl/
配置GOROOT,值为go安装路径
配置GOPATH:值为你项目或者练习项目的路径,自己创建,这里我是在golang安装目录在新建一个空的olangWorkSpace文件下。
配置path
package main
import "fmt"
func main() {
fmt.Println("hello")
}
1. var a int (有默认值,默认值为0)
2. var a int = 100
3. var a = 100
4. a := 100
5. var a, b int = 1, 2
6. var(
a int = 100
b string = "b"
)
注:单个变量声明中,1、2、3是可以声明全局变量,4不可以。
定义常量:const a := 1
iota使用在const枚举中
const (
//可以在const()添加一个关键字iota,每行的iota都会累加1,第一行的iota的默认值是0
a, b = iota+1, iota+2 // iota = 0, a = iota + 1, b = iota + 2, a = 1, b = 2
c, d // iota = 1,c = iota + 1, d = iota + 2,c = 2, d = 3
e, f //iota = 2, e = iota + 1, f = iota + 2,e = 3, f = 4
g, h // iota * 2,iota *3 ll iota = 3, g = iota * 2, h = iota * 3,g = 6, h = 9
i, k //iota = 4, i = iota * 2, k = iota * 3 , i = 8, k = 12
)
1.函数
1. func f1(a int, b int) int {
return a+b
}
2. func f2(a int, b int) (int, int) {
return a, b
}
3. func f3(a int, b int) (r1 int, r2 int) {
r1 = a * 10
r2 = b * 10
return
}
4. func f4(a int, b int) (r1, r2 int) {
r1 = a * 10
r2 = b * 10
return
}
go执行流程
2.导包
指针存的是地址,并且可以直接修改地址里的值,java改引用类型的值并不是改地址里的值,而且赋值另外一个值的地址。
&是传地址、*是取地址
使用
package main
func main() {
var a int = 1
var b int = 2
swap(&a, &b)
println(a)
println(b)
}
func swap(pa *int, pb *int) {
var temp int = *pa
*pa = *pb
*pb = temp
}
二级指针
var a int = 1
var p = &a
var pp **int = &p
defer是最后执行的,有点像java的final
defer println("1")
println("2")
//结果为2 1
多个defer是以压栈的形式执行的
defer println("1")
defer println("2")
// 结果为2 1
defer晚与return执行
先执行return再执行defer
数组:定义的时候要指定长度
func main() {
// 定义固定长度数组,默认值为0
var a [10]int
b := [2]int{1,2};
// 调用函数,传参只能传长度一样的形参,并且数组传参是值传递,在其他函数中修改值,不影响原来值
toString(b)
}
func toString(myArray [2]int) {
}
slice:定义的时候不要指定长度,会自己扩容
func main() {
var a []int
b := []int{1, 2}
// 调用函数,数组传参是引用传递,在其他函数中修改值,会影响原来的值
toString(b)
}
func toString(myArray int) {
}
遍历数组或者slice
// 如果是数组行参要指定长度,func myfor(nums [len]int){}
func myfor(nums []int) {
// 1.第一种遍历
for key, value := range nums {
fmt.Println(key, value)
}
// 第二种遍历
for i := 0; i < len(nums); i++ {
}
}
slice四种定义方式
// 1、初始化长度和默认值
slice := []int{1, 2, 3}
// 2、声明一个slice,但是并不分配空间,这个时候长度为0,需要使用make方法进行扩容
var slice []int
slice = make([]int, 3)
// 3、声明一个slice,同时初始化空间长度
var slice []int = make([]int, 3)
// 4、
slice := make([]int, 3)
slice追加
// 创建一个长度为2容量为5的切片make(int[], len, cap)
s := make([]int, 2, 5)
// 追加的时候如果len=cap,则会进行扩容,每次扩容的长度为cap
s = append(s, 1)
// 输出为3 5 [0 0 1]
fmt.Println(len(s), cap(s), s)
slice切片:类似python的切片,注意slice的切片是引用传递
// 创建一个长度为2容量为5的切片make(int[], len, cap)
s := make([]int, 2, 5)
// 切完出来的数据是引用传递,修改新值会影响原来的值
s1 := s[0:2]
s1[0] = 100
//结果为[100 0] [100 0]
fmt.Println(s, s1)
map传参也是引用传递
定义map
// 第一种声明方式,使用map进行创建,可以传入容量,没有的话默认为1,每次扩容的长度为容量
myMap1 := make(map[int]string)
// 第二种声明方式,声明的时候初始化赋值
myMap2 := map[int]string{
0: "one",
1: "two"
}]
map使用
myMap1 := make(map[string]string)
// 增加
myMap1["a"] = "one"
// 修改
myMap1["a"] = "two"
// 删除
delete(myMap1, "a")
相当于java的class
type Book struct {
title string
author string
}
// 这样传递是值拷贝,在函数中修改book,不会影响原来的book
func toString(book Book){}
func main() {
var book1 Book;
book1.title = "a";
bokk1.author = "b";
}
func main() {
hero := Hero{"吕竟", 100}
hero.SetName("吕竟1")
hero.Show()
}
type Hero struct {
Name string
level int
}
func (this *Hero) GetName() string {
return this.Name
}
func (this *Hero) SetName(newName string) {
this.Name = newName
}
func (this *Hero) Show() {
fmt.Println("name: ", this.Name, "level: ", this.level)
}
func main() {
z := Z{F{"lv", "nan"}, 10}
z.Show()
}
// 定义父类
type F struct {
name string
sex string
}
// 父类方法
func (this *F) Show() {
fmt.Println("name: ", this.name, "sex: ", this.name)
}
// 重写父类方法
func (this *Z) Show() {
fmt.Println("我是子类")
}
// 子类继承父类
type Z struct {
F
age int
}
注意:子类要实现父类的所有接口方法,才算实现了父类接口
// 定义一个接口
type AnimalF interface {
Sleep()
Call() string
}
// 定义一个子类狗实现接口
type Dog struct {
name string
}
func (this *Dog) Sleep() {
fmt.Println("狗在睡觉")
}
func (this *Dog) Call() string {
return "旺旺"
}
// 定义一个子类猫实现接口
type Cat struct {
name string
}
func (this Cat) Sleep() {
fmt.Println("猫在睡觉")
}
func (this Cat) Call() string {
return "喵喵"
}
// 多态
func getAnimal(f AnimalF) {
f.Sleep()
}
func main() {
animal := &Cat{"喵酱"}
animal.Sleep()
getAnimal(&Cat{"猫猫"})
getAnimal(&Dog{"狗狗"})
}
万能类型interface{},go的所有类型都实现基础了interface{}类型
万能类型
func show(o interface{}) {
fmt.Println(o)
}
type Book struct {
name string
}
func main() {
book := Book{"书籍"}
show("a")
show(1)
show(book)
}
断言
// value是arg的值,ok是true或false
value, ok := arg.(string)
每一个变量都有两个指针pair
使用
import (
"fmt"
"reflect"
)
func show(o interface{}) {
fmt.Println(o)
}
type Book struct {
Name string
Price int
}
func (this Book) Call() {
fmt.Println(this)
}
func main() {
book := Book{"书籍", 10}
// 反射获得类型
bookType := reflect.TypeOf(book)
// 反射获得值
bookValue := reflect.ValueOf(book)
fmt.Println(bookType.Name(), bookValue)
// 反射获得内部属性
for i := 0; i < bookType.NumField(); i++ {
// 获得属性名
field := bookType.Field(i)
value := bookValue.Field(i).Interface()
fmt.Println(field.Name, value)
}
// 反射获得方法
for i := 0; i < bookType.NumMethod(); i++ {
m := bookType.Method(i)
fmt.Println(m.Name)
}
}
变量名 数据类型 key: value key: value ....
使用reflect.TypeOf(&变量).Elem()的时候记得传参数用指针
type Book struct {
Name string `info:"吕竟" doc:"是帅哥"`
Price int `info:"10"`
}
func (this Book) Call() {
fmt.Println(this)
}
func main() {
b := Book{"吕", 1}
t := reflect.TypeOf(&b).Elem()
// 通过反射获得标签
for i := 0; i < t.NumField(); i++ {
taginfo := t.Field(i).Tag.Get("info")
tagdoc := t.Field(i).Tag.Get("doc")
fmt.Println(taginfo, " ", tagdoc)
}
}
标签在json中的应用
type Book struct {
Name string `json:"name"`
Price int `json:"rmb"`
}
func main() {
b := Book{"红楼梦", 1}
// 结构体转json
jsonStr, err := json.Marshal(&b)
if err != nil {
fmt.Println("错误")
return
}
fmt.Println(b)
fmt.Println(string(jsonStr))
// json转结构体
b1 := Book{}
json.Unmarshal(jsonStr, &b1)
fmt.Println(b1)
}
GoMAXPROCS限定的P的个数=CPU核数/2
会不断去监听channel,如果channel有值则会执行range把值取出
for data := range c {
fmt.Println(data)
}
一次性监听多个channel
select {
case <- chan1:
// 如果chan1成功读到数据,则进行该case处理语句
case chan2 <- 1:
// 如果成功向chan2写入数据,则进行该case处理语句
default:
// 如果上面都没有成功,则进入default处理流程
}
国外的网站,如果设置了GOPROXY,这个就不用设置了。
4. GONOPROXY