[toc]
learn from book <TheGoProgrammingLanguage> ##2020-1-18 ###学习了tag
git tag -a v0.1.0 -m "release 0.1.0 version"
-
tag做为工程的一个时间点,每个tag仅于一个commit号绑定。系统中自然不容许相同的tag。
-
tag不会像branch,一旦commit新的工程,tag不会更新。
-
tag也属于标识,不push只会留在本地。本例中v0.2不在github,只在本地有。
-
若目前tag分支与master脱离,以及 若此时的tag就是master分支但是 没有push master。都不会影响github上的master。v0.1 和v0.3 的readme.md与本文不符就是证明。
所以 1.请在需要tag时,commit后再tag出一个时间点(一个分支),push完tag后请立刻回到原来所在分支(branch)。 2.或者 tag + commit号来指定项目时间点来打标签。
###学了书 hellworld
中括弧有规则
大写pubilc 小写 private
##2020-1-25 ###banch
git checkout -b XXX 新建
git checkout xxx 切换
git branch -d xxx 删除
git merge xxx 当前HEAD向(与)xxx处合并
- 在合并时,如果当前HEAD为xxx的父快照,则一般会
Fast-forward

一般是自动合并成功的,因为快照层的操作,也不需要再commit
- 合并时 ,若HEAD与xxx快照分叉,且对同一文件有修改,则会冲突
CONFLICT

显然此时自动合并失败,需要手动调整。可以从git status观察到冲突文件,并在文件中观察到
<<<<<<< HEAD:Readme.md
=======
>>>>>>> iss3:Readme.md
你可以手动去修改这些文件,比如去掉你不要的内容 以及 <<<<<<< 、>>>>>>> 、=======
或者借助工具修改这些文件
但是都意味着需要重新add与commit,以下是修改后并add后的git status
Clear 还需要commit哟 
在go中
-
[5]int 为声明数组
数组属于变量,赋值(=)及函数传参时复制副本。故若a = b,则a与b之后操作互不干涉。 -
[]int 为声明切片
数组切片名属于指针,赋值及函数传参时复制地址。故若 a = b ,则ab之后同名。 -
此外,在go自己的内存自动回收机制中,似乎允许函数外指针指向函数内声明的数组(变量)
若在C中函数结束,函数内声明变量销毁,会出现函数外指针指向空的错误。
就像使用master一样,commit&&push注意,master就不会再动了。你现在commit将更新iss3
-
interface{}
一个没有实现要求的接口 其性质为指针,能够接受一切类型,就像C#中的object C++的空指针 是一切的父类 -
...
实际上是切片的特殊语法 也可以归类至不定参数 当函数func funca(arge []int ){} 则输入应为 funca([]{1,2,3,4})
当函数func funca(arge ...int ){} 则输入应为 funca(1,2,3,4)、funca(arge...) 就是方便
##2020-1-27 ###branch -b -iss4 今天我们就来建立iss4 并准备合并 iss3 iss4 master
####type
定义 同名 同define
####类方法
首先不仅仅可以给struct 也可以给内置类型定义方法,以及指针不行!!
func (a structname) xxxx(input) output
a 在此处的身份很像== 必须显式表达的this \
当然 go没有类 class, 因为任何类型都可以声明自己的方法,而go有又禁止继承,或者说由接口更加通用地代替继承。
所以go只有struct 用法就是类
type xxxx struct{} #####初始化 以 type Rect struct{}为例
- rect1 := new(Rect) \
- rect2 := &Rect{} \
- func NewRect() *Rect{}
- 1 成员方法中,"this"对象是否使用指针 . 声明类方法时,
func (a structname) xxxx(input) output
如果希望a在运行函数后能够改表,则需要让a为指针 即 a *structname
否则的话 a 依旧是个副本(当然若变量本身是指针,则是特殊情况)
- 2 go 中没有 ->.
在go中 指针没有字段(成员、方法),【注:指针是不允许有成员方法的】所以 以下两端代码将会没有歧义而等价:
设 a *structname
(*a).Area() <==> a.Area()
所以自然就没有 -> 的必要了。
但需要注意,只有涉及字段(成员)的结构体struct ,可以因上文原因同义。本质上
*a 与 a 并不同义
- 3 new 是给 struct用 make 是给 map slice chan
都得到的是指针(&struct) ##2020-1-29 ###接口
注意GO语言对指针的自动翻译
注意同样会存在 (*a).xxx 自动<==> a.xxx
以下代码type LessAddr interface{
Less (b Integer) bool
Add (b Integer)
}若a为指针则自动生成 func (a *Integer) less (b Integer){ ....a to a* } 即以下合法
type Integer int //这句必须存在
var a Integer =1;
func Less (b Integer) bool
var b LessAddr = &a;
//此时 Less(b)将自动变为 less (b *) ####接口查询 类查询 if _,ok:= b.(LessAddr) ok{
b 满足接口吗 当然!
if _, ok:= c.(*structname) ; ok { \
c 的指向对象是类structname么? 请注意c本身可能是接口或类。\ 返回第一个参数代表一个 转换接口/类型后的 同名
####类型查询
如果是问是不是内置类型 则用 c.(type)
switch v.(type) 请和switch配合使用
- 1 成员方法中,"this" 类型必须是type定义的,且不能是接口 否则报错
你不能直接!为内置类型添加方法
type miao struct{ //...
func (this miao) xxx()(){ //...
- 2 成员方法的另一种定义方法就是,struct添加函数数据成员(类似函数指针)
type miao struct{
do func ()()
//... }
func xxx()(){ //...使用方法如下:
nya:=&miao{do:xxx }
nya.do()
- 3 接口查询时,括弧不可省去 以及结构是返回的第二个参数
##2020-1-30 ###test Golang 单元测试对文件名和方法名,参数都有很严格的要求。例如:
- 1、 文件名必须以 _test.go 结尾
- 2、方法名必须是 Test 开头
- 3、方法参数必须是 t *testing.T 或 b *testing.B ##2020-2-1 ###channel 向管道输入 阻塞直至数据被输入至缓冲区(当缓冲区为0或者缓冲区不足都阻塞)
c<-'A'
从管道取出数据 阻塞直至数据存在于管道(如果缓冲区为0,则输入端会阻塞直至输出端取走数据)
fmt.Println(<-c)
miao <- 1; ###select select 对case选择是无序的、乱序的、以及如果case两个以上满足条件,就都执行的 !
全局首次操作,sync.Once once.do保证全局唯一性操作 (就是初始化) 保证该函数无论开出多少次协程,只会运行一次
var once sync.Once func xxx(){
once.do(yyy)
} ###注意
- fatal error: all goroutines are asleep - deadlock! 主程序堵塞,且没有其他协程运行(就是没有其他协程能帮(maingoroutine)主协程解堵塞)
一种可能是声明channel时没有开缓冲空间,此时只剩(maingoroutine)主协程在运行时,往channel中读、写都会报错
make(chan int);
另一种情况就是在主程序读操作阻塞,且此时又只剩主协程,常见现象为询问channel关闭时,channel没数据也没关闭
_,x :=ch
- 第一种情况
如果声明channel没有给缓冲空间, 那对此channel写时,因为没有缓存空间只能阻塞,直到有协程能读时才会解除阻塞。 在此条件下,本协程的程序一旦阻塞(尽管本协程下文有读操作,但是因为堵塞永远也不会等到其执行),只能靠其他同时运行的协程解决。
如果发生这种阻塞且程序只有正在阻塞的main goroutine在运行意味着阻塞永远不会解除,系统会报错 \ - 第二种情况
close对于一个channel来说也是个写数据,但比较特殊,其确认方法即读数据。在channel有数据时,正常返回数据。在关闭时第二参数正常返回false 没数据、没关闭、又只剩main goroutine,还是那句话 永远也等不到下文!
fatal error: all goroutines are asleep - deadlock!
解决方法:
- 1 更改逻辑,添加goroutine 使channel完成一写一读
- 2 为channel 添加缓存 make(chan int, 1024);
- 3 尝试让问题channel在主程序之外执行
- select 的选择是无序的、乱序的、以及如果满足两个以上就都执行的 ! ##2020-2-2 ###TCP 测一下go与C++相连状况
- C++socket编程的数据格式与go不同
C++ 的send/recv主要使用 \0来结束字符串的传输(当然要小于参数len)
在go中需要使用\000来代表 C++的 \0
go中 使用io.EOF来判定结束字符串的传输,C++完全无法输出该符号
因为C++无法给出对方go终端来自报错模块的专有符号, C++发完信息后,go中,虽然会结束一个conn.Read 但是不会 触发err == EOF,而是err == nil 代表没发送完。并接收到C++send参数中len长的字符串,在C++中\0后面的部分也会发送过来!!
- string(result) 遇到\0会停止喵
- bytes 似乎可以无限长喵 用write来输入
- TCP sever实例
##2020-2-3 ###HTTP
- http 注册路由中需要提供url与func的对应
- url与http 函数handler应该从虚拟目录部分开始吧?
- Content-Type post
- 重定向 本服务器无法处理该请求 返回3XX 与对应新的location给客户端
- cookie http验证身份用
##2020-2-6 ###RPC
- TCP+RPC 应用实例
- 如果在用到God序列化时,参数对象存在小写
当然会报错!!
在GO中,小写就是私有。小写的方法,小写的参数,大写的struct内小写的参数。都是不能对外访问的,所以报错
如:
type AnsList struct {
ans int
ans2 string
}2020/02/06 21:03:17 rpc: gob error encoding body: gob: type main.Ans has no exported fields 2020/02/06 21:03:17 reading body EOF
- 结构体内声明切片时,初始化出现报错。链接:结构体的使用
Missing type in composite literal
因为数组的声明和赋值要是这个样子的。
s := []string{“值1”,“值2”},所以在结构体初始化的时候,数组前面也要加上类型才可。
###JSON
JSON 加码与解码
b,err :=json.Marshal(s);
err = json.Unmarshal(b,&s)
面对 未知结构体的json码时
var r interface{} //用空接口 接收数据
err = json.Unmarshal(b,&r)然后一步一筛查其类型与所含有成员 刚接收完数据的r现在是map[string]interface{}
statemap ,ok := r.(map[string]interface{});
//r是map 提取成员Authors
author,ok2 :=statemap["Authors"].([]interface{});
//key "Authors"存在 提取第一个成员[0]
_,ok3 :=author[0].(string)
//是map[string][]string
- 注意不要跳步 author([]interface{})是不能和[]string 直接做比较的(判为 不符合)
author,ok5 :=statemap["Authors"].([]string);
ok5 ==false
##2020-2-9 学习了6 7 8 章 ###注意
- 接口总是指针,请赋值指针/地址给接口,如果赋值给接口 值会报错找不到符合接口的方法
var a inter=2;
var b LessAddoneer = &a; // yesvar b LessAddoneer = a;// error \
Cannot use 'a' (type inter) as type LessAddoneer in assignment Type does not implement 'LessAddoneer' as 'Addone' method has a pointer receiver
- interface{} 空指针可以指向任何 ,但是GO没有继承。所以当得到r interface{}时。只能找到赋值给空指针时准确的类/接口,并赋值回去
var RR interface{}
RR = miao; \if _ ,ok2 := RR.(Miao2);
ok2==trueif mm ,ok4 := RR.(ani); ok4
ok4==false