对于go的学习,需要注意的地方。
1、特别注意,go中可以使用go env命令查看我们可以在环境变量中设置的变量。
2、一般的输出使用内建函数print或者println就可以了,fmt.printXXX函数有更多的作用,比如格式化输出
3、
4、系统输出数组喜欢用[]并使用空格作为元素分隔,所以不要以为[]和空格是数据本来就又的,这点需要注意!
5、java以文件学习,因为java中国一个文件对应一个类,而go以模块学习,因为go中都是直接调用模块的函数,而模块的函数都分布在模块下的文件里面。
6、代码块中的:=短式声明在代码块外不起作用,另外,多使用go tool vet -shadow your_fil.go检查隐藏变量。
7、GOBIN环境变量可以让go install的exe文件放置在GOBIN下。
8、函数有多少个返回值,在给变量赋值的时候就需要有多少变量需要来获取这些返回值,但是如果使用range就可以只获取第一个返回值,这点在range可以操作channel就可以看出来了。
9、使用go get url之后,使用import "url"就可以使用这个包了。
10、可以再var()和const()中声明重复的变量,可以再函数中使用:=短式声明多个变量,其中有变量是与上面的变量重复的,这样也是允许的。但是需要注意,在匿名函数中重复声明匿名函数外的变量,并不会影响匿名函数外的变量,这点需要注意。
11、一般使用组合来实现继承关系,所以可以很容易查找到继承的关系,也就可以更好的给函数传值了,一般不会要求通过看函数实现来定位继承关系。
在go中调用C/C++是非常容易的,可以分为两种:1、可以直接嵌入。在import “C”上使用//或者/**/然后再里面添加需要的例如#include xxx或者代码。这里还可以使用#cgo操作cgo命令,例如#cgo LDFLAGS : -L ./ - lfoo告诉编译器,链接当前目录下lfoo共享库,也就是so文件,如果在编译中使用so库,使用命令go build -ldflags="-r DIR",其中DIR是so库目录。2、在src下创建一个专门存放c代码的文件夹,然后在里面添加h,c,go文件,go文件用于将c,h包装给外面使用。例如下面的例子:
fun.c:
#include <stdio.h> #include <stdlib.h> char* MySecret() { return "my secret not tell anybody"; }
fun.h:
extern char* MySecret();
fun.go
package misc //注意,这里可以使用#include dir来引进某个c库,实际上include就是为了引进文件 //C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt下有我们需要 //的如stdlib.h等文件 // #include "fun.h" import "C" func MySecret() string { return (C.GoString(C.MySecret())); }
网络编程大致上分为b/s,c/s两种。而go中,net实现底层网络功能,net.http实现高级的网络功能。net模块一般用于c/s,而net.http则是c/s,b/s都可以。但是无论是哪种实现方式,其实都是客户端请求数据,而服务端监听并给予数据。
在go中使用net.Dial函数就可以实现客户端的socket功能了,在服务端有net.Listen函数作为服务端的socket功能。这是go的net底层的功能,也是实现c/s的基础方式。
对于常见的方式,应该是使用net.http模块的功能。一个url对应一个网络资源,常见的Get,Post,Put,Delete分别对应增删查改,get查询,post修改,put增加,delete删除。网页的获取方式是get,所以一般get不会被拒绝。这里客户端一般使用net.http.Get()或者net.http.Post()进行数据获取,而服务端使用net.http.ListenAndServe()监听并操作数据,如果是浏览器,其实也是通过net.http.Get()获取数据的,net.http.Post()交互数据的。
对于go的包,不要命名为main,all,std等,不要再src下创建main包,因为在src下创建一个文件并添加package main和main函数就可以作为程序的入口文件了。在引用自己项目的东西的时候,需要使用import "./xxx"而不能是直接import "xxx",不然会在编译的时候出错。这样做其实是为了不和go系统下的文件混淆,当然,如果直接将项目放到GOPATH下的第一个路径,那么可以直接使用import "xxx",因为这个时候,项目被当成系统文件了。
另外,自己的项目模块的命名最好不要跟系统的模块名字一样,因为系统分辨不出来。
最后需要注意,在go项目下点号"."代表的是当前项目路径。
使用go get命令下载并编译的文件会放在GOPATH的第一个路径下,另外,我们的项目也是需要添加到GOPATH下的。最后注意,项目定位到项目名,而不是工作空间名。另外注意,对于需要翻墙的,如果使用cmd,putty,一般网上的代理配置完之后都没用,可以使用git clone直接下载需要翻墙的部分,当然git需要配置代理。然后使用go get下载不用翻墙的部分。其实go get就是使用git clone之后编译下载的项目而已。
当然我们可以使用gopm这个包管理工具,这个工具可以用于安装,搜索,更新和分享go包,所以对于go的第三方包的管理,使用gopm是个不错的选择。
在go中只有不可修复的错误才使用defer,panic(),recover(),其他的用error,一般使用errors.New,fmt.Errorf函数都可以创建实现error接口的错误对象。这里注意,errors本身就是用于操作error的,而fmt则是格式化错误输出。
应该说defer只是延迟操作而已,真正的错误操作是panic和recover函数。其中,panic是保存一个异常信息,因此多次调用panic,当前异常会覆盖上一个异常。其实recover可以在任何地方调用,只是如果没有panic的错误,那么返回的是nil,所以recover只有在defer中调用才能得到异常信息了,而且panic之后程序就返回了。最后需要特别注意,recover需要在defer中直接调用,或者defer后的函数或者匿名函数里面直接调用才可以。不然返回nil,这点可以在进程工作空间看出。
go中有errors,bytes,strings三个模块分别对应error,byte,string的操作封装,应该说go很喜欢使用XXXs来封装对XXX的操作这种命名模式。当然了,XXutil这种也很常见,比如ioutil模块用于辅助io操作。
go中,string和[]byte其实是一样的,只是被定义成了不同的类型,并且string拥有了函数。所以bytes,strings两个模块的函数很多很相似,比如两个模块都有去空格函数。应该特别注意,java中String封装的很多函数,在go中就在strings模块中。同样的bytes封装了[]byte的操作。同时注意,封装了很多很好用的正则函数。最后注意,bytes,strings都封装了相应的Reader,Writer类,和NewReader,NewWriter函数,这也是为了读写操作封装的。
Reader里面的数据读取一次之后就没有了,所以我们可以使用ioutil.FindAll函数得到字节数组,然后将字节数组传递给bytes.NewReader生成Reader,这样就可以再次操作Reader了。
go中,最应该掌握的是builtin模块,这个模块里面的都是内建函数,这个模块里面的函数都是用于操作内建数据类型的。比如len函数就是用于得到内建数据类型的数据的长度的。另外,nil的==,!=比较只能是在内置函数中进行,这是因为在go中nil被定义了类型。最后注意,除了指针类型,其他的内置数据类型不能修改指针地址。
未完成
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)