diff --git a/source/c01/c01_01.rst b/source/c01/c01_01.rst index 019cf89e47dad738ca7bc56e3d862d045350aa11..7a79ddf039849021c5be8019b7b82eb081dc326e 100644 --- a/source/c01/c01_01.rst +++ b/source/c01/c01_01.rst @@ -86,68 +86,205 @@ Go运行器。 3. 配置 VS Code 环境 -------------------- -提前设置用户级的环境变量 +下载 VS Code +~~~~~~~~~~~~ + +要使用 VS Code,咱首先第一步得安装它。 + +官网下载地址是:https://code.visualstudio.com/Download + +但是在这里获取的下载链接非常的快,没有使用代理的同学,几十M的软件可能得下载一天。 + +那么有什么办法呢? + +这里教大家一个方法: + +在官网获取的下载链接是这样子: :: - GOPATH = F:\Go-Player - PATH = %GOPATH%\bin # 以追加的方式 + https://az764295.vo.msecnd.net/stable/c185983a683d14c396952dd432459097bc7f757f/VSCodeUserSetup-x64-1.55.0.exe + +我们看到前面的域名是\ ``az764295.vo.msecnd.net`` ,你只要将这个域名 +``vscode.cdn.azure.cn`` 就可以。 + +更换后的下载链接是这样子: + +:: + + https://vscode.cdn.azure.cn/stable/c185983a683d14c396952dd432459097bc7f757f/VSCodeUserSetup-x64-1.55.0.exe + +再把这个链接贴到你的下载工具(我使用的是 FDM),下载速度就飞快了。 + +设置环境变量:GOROOT +~~~~~~~~~~~~~~~~~~~~ -昨天评论区有人问,GOPATH 和 GOROOT 是什么?为什么需要设置?回想一下 你学 -Python 的话,安装 Python -解释器的时候,是不是也要设置环境变量?这里也是类似。 +在下载并安装好 Go 后,需要对环境变量进行一些配置,其中最重要的就是 +GOROOT。 -GOROOT :在GO语言中表示的是 -Go语言编译、工具、标准库等的安装路径,通过它可以告诉系统你的 go.exe +在GO语言中表示的是 +Go语言编译、工具、标准库等的安装路径,通过它可以告诉系统你的 ``go.exe`` 是放在哪里,不设置的话,你后面执行 ``go get`` 、\ ``go install`` 的时候,系统就不认识它了。 -而 GOPATH环境变量则表示 -Go的工作目录,这个目录指定了需要从哪个地方寻找GO的包、可执行程序等,这个目录可以是多个目录表示。这里我设置成我的工作空间(目录你可以自己定) -:\ ``F:\Go-Player``\ ,如果不设置的话 ,默认是在你的用户目录下的 go -文件夹。 +右键 ``我的电脑`` ,点击属性 -这时要再说一点,GO 项目中,一般来说它的工作目录结构是这样的: +|image14| -- bin目录:包含了可执行程序,注意是可执行的,不需要解释执行。 +再点击 ``高级系统设置`` -- pkg目录:包含了使用的包或者说库。 +|image15| -- src目录:里面包含了go的代码源文件,其中仍按包的不同进行组织。 +在弹出来的窗口点击 ``环境变量`` -所以后面我的创建的GO工作目录,也是按照这个标准来,先说明一下。 +|image16| -接下来,要开始配置 VS Code 环境。 +点击系统环境变量点的 PATH,再点击编辑 -打开你的 VS Code软件,先确认你设置的环境变量已经生效,点击 ``Terminal`` --> ``New Terminal``\ ,使用 cmd 命令查看环境变量。 +|image17| -|image14| +在弹出来的窗口中,新增一条 item,内容如下,这个目录是 go.exe 所在的目录 -如上图所求,我的环境变量是OK的,如果你的输出是指向你的用户目录:\ ``%USERPROFILE%\go`` -建议你不要折腾(因为我无论重启多少次 VS -Code,其记录的GOPATH始终指向%USERPROFILE%:raw-latex:`\go`), -直接重启你的电脑。 +|image18| -好了之后,我们要从 github -上下载两个仓库,之所以要手动下载,是因为有墙的存在,在线安装的话,很多插件你会下载失败。 +设置完成后,可以在 cmd 窗口中,运行 +``go version``\ ,如果可以正常运行说明,环境变量正确配置且已经生效。 -创建目录 ``src/goland.org/x/``\ ,并进入此目录,执行命令 +如果执行失败,你可能需要重启电脑才能生效了噢(反正我是这样) -.. code:: shell +设置环境变量:GOPATH +~~~~~~~~~~~~~~~~~~~~ - $ git clone https://github.com/golang/tools.git - $ git clone https://github.com/golang/lint.git +设置完 GOROOT,还要设置 GOPATH,它会告诉 Go 你的项目是在哪个目录? -点击 ``File`` - ``Open Folder`` 安装两个插件: +这个环境变量,你可以像 GOROOT +一样通过电脑系统的环境变量来设置,在那里设置一个默认的工作目录(这个目录你可以自己定)。 -第一个是:Go 语言的扩展插件 +|image19| -|image15| +不过这种方法极不推荐,因为你不可能只有一个项目,我们每个项目都有自己的 +GOPATH。习惯的做法是可以使用 ``go env`` 命令来设置 -第二个是:Code Runner,让你的 VS Code 能够编译运行 Go 的程序。 +:: -|image16| + $ go env -w GOPATH=E:\VMP-Code\Golang + +如果你已经在系统的环境变量中设置了 GOPATH ,那么一定移除掉,才能使用 +``go env -w`` 去设置,否则会报如下的警告 + +:: + + warning: go env -w GOPATH=... does not override conflicting OS environment variable + +如果你移除了还报这个错误,那可能需要你重启电脑(反正我是这样) + +安装 Go 扩展 +~~~~~~~~~~~~ + +Go Extension +^^^^^^^^^^^^ + +Go 语言的扩展插件,提供了代码运行、导航、调试等最基本的功能。 + +这是是一年多前(2020年初)的截图,当时的开发者还是 Microsoft + +|image20| + +现在(2021年初)再去搜索一看,发现开发者已经变成了 Google 的 Go +开发团队了。 + +|image21| + +Code Runner +^^^^^^^^^^^ + +编写完代码后,想运行这个 go 文件,通常情况下你得通过下面 VSCODE +提供的入口去运行,是比较麻烦的。 + +|image22| + +点击 ``create a launch.json file`` 就会在项目根目录下创建一个 json +文件,创建完成后,运行的边栏就变成如下模样,再点击 +那个三角运行按钮,就可以运行它了。 + +|image23| + +使用这种方法,需要安装一个 ``dlv``\ ,VS Code +会提示你安装它,安装完成后你会在 bin 目录下发现 ``dlv.exe``\ 。 + +|image24| + +这种运行方法,虽然可行,但是操作路径还是有点长。 + +最符合用户使用习惯的应该是,直接有一个 ``运行`` 的按钮的,例如这样 + +|image25| + +或者通常快捷键,或者右键就有运行的选择项。 + +|image26| + +VS Code 本身不提供这样的功能,你需要安装一个叫 ``Code Runner`` +的扩展,安装后不需要重启 VS Code 就会失效。 + +|image27| + +运行 Hello World +~~~~~~~~~~~~~~~~ + +以上都配置好了,就可以在 VS Code 上编写并执行代码,代码如下 + +.. code:: go + + package main + + import ( + "fmt" + ) + + + func main() { + fmt.Println("Hello, Golang") + } + +使用 Ctrl + Alt + N ,或者右键选择 ``Run Code`` 就可以执行该 go 文件。 + +|image28| + +设置环境变量:GOPROXY +~~~~~~~~~~~~~~~~~~~~~ + +由于国内的一些网络问题,导致我们无法直接拉取 go +的一些工具包,这时候就要借助大神们搭建的代理地址来下载了。 + +最经常使用的是代理地址是:\ ``https://goproxy.cn`` + +:: + + go env -w GOPROXY=https://goproxy.cn,direct + +项目目录解析 +~~~~~~~~~~~~ + +这里要说一点,GO 项目中,一般来说它的工作目录结构是这样的: + +- bin目录:包含了可执行程序,注意是可执行的,不需要解释执行。 + +- pkg目录:包含了使用的包或者说库。 + +- src目录:里面包含了go的代码源文件,其中仍按包的不同进行组织。 + +所以后面我的创建的GO工作目录,也是按照这个标准来,先说明一下。 + +4. 下载 Go 工具插件 +------------------- + +创建目录 ``src/goland.org/x/``\ ,并进入此目录,执行命令 + +.. code:: shell + + $ git clone https://github.com/golang/tools.git + $ git clone https://github.com/golang/lint.git 随便点开一个 go 文件,在你的右下角会提示要你安装一些工具,安装的包有些由于墙的原因,无法下载,为了保证下载顺利,可以设置一下代理。 @@ -158,23 +295,25 @@ Code,其记录的GOPATH始终指向%USERPROFILE%:raw-latex:`\go`), 然后再点击 ``Install All`` -|image17| +|image29| 然后你在 OUTPUT 就能看到安装进度 -|image18| +|image30| 安装的 exe 文件会放在 %GOPATH%/bin 下,也就是 ``F:\Go-Player\bin`` -|image19| +|image31| 而此的 src 目录结构是这样的 -|image20| +|image32| 到这时环境配置完成,编写 HelloWorld,并运行查看输出,一切完成。 -|image21| +|image33| + +- gopkgs: 4. 配置环境变量 --------------- @@ -243,7 +382,7 @@ Code,其记录的GOPATH始终指向%USERPROFILE%:raw-latex:`\go`), -------------- -|image22| +|image34| .. |image0| image:: http://image.iswbm.com/20200607145423.png .. |image1| image:: http://image.iswbm.com/20200102220841.png @@ -259,13 +398,25 @@ Code,其记录的GOPATH始终指向%USERPROFILE%:raw-latex:`\go`), .. |image11| image:: http://image.iswbm.com/20200127192748.png .. |image12| image:: http://image.iswbm.com/20200102224417.png .. |image13| image:: http://image.iswbm.com/20200102225550.png -.. |image14| image:: http://image.iswbm.com/20200109210630.png -.. |image15| image:: http://image.iswbm.com/20200108202934.png -.. |image16| image:: http://image.iswbm.com/20200109153948.png -.. |image17| image:: http://image.iswbm.com/20200109210654.png -.. |image18| image:: http://image.iswbm.com/20200109211543.png -.. |image19| image:: http://image.iswbm.com/20200109213056.png -.. |image20| image:: http://image.iswbm.com/20200109214117.png -.. |image21| image:: http://image.iswbm.com/20200109154657.png -.. |image22| image:: http://image.iswbm.com/20200607174235.png +.. |image14| image:: http://image.iswbm.com/20210405094512.png +.. |image15| image:: http://image.iswbm.com/20210405094719.png +.. |image16| image:: http://image.iswbm.com/20210405094742.png +.. |image17| image:: http://image.iswbm.com/20210405094931.png +.. |image18| image:: http://image.iswbm.com/20210405095053.png +.. |image19| image:: http://image.iswbm.com/20210405095326.png +.. |image20| image:: http://image.iswbm.com/20200108202934.png +.. |image21| image:: http://image.iswbm.com/20210405113213.png +.. |image22| image:: http://image.iswbm.com/20210405113905.png +.. |image23| image:: http://image.iswbm.com/20210405114834.png +.. |image24| image:: http://image.iswbm.com/20210405125424.png +.. |image25| image:: http://image.iswbm.com/20210405124543.png +.. |image26| image:: http://image.iswbm.com/20210405114049.png +.. |image27| image:: http://image.iswbm.com/20210405124219.png +.. |image28| image:: http://image.iswbm.com/20210405110854.png +.. |image29| image:: http://image.iswbm.com/20200109210654.png +.. |image30| image:: http://image.iswbm.com/20200109211543.png +.. |image31| image:: http://image.iswbm.com/20200109213056.png +.. |image32| image:: http://image.iswbm.com/20200109214117.png +.. |image33| image:: http://image.iswbm.com/20200109154657.png +.. |image34| image:: http://image.iswbm.com/20200607174235.png diff --git a/source/c02/c02_04.md b/source/c02/c02_04.md index 756de7994e55c57296a19ed01262ffc0870d7813..d3c293cd6579d32a9b9c2b4c8dc92373ad33d969 100644 --- a/source/c02/c02_04.md +++ b/source/c02/c02_04.md @@ -81,7 +81,7 @@ exit status 2 t, ok:= i.(T) ``` -和上面一样,这个表达式也是可以断言一个接口对象(i)里不是 nil,并且接口对象(i)存储的值的类型是 T,如果断言成功,就会返回其类型给 t,并且此时 ok 的值 为 true,表示断言成功。 +和上面一样,这个表达式也是可以断言一个接口对象(i)里不是 nil,并且接口对象(i)存储的值的类型是 T,如果断言成功,就会返回其值给 t,并且此时 ok 的值 为 true,表示断言成功。 如果接口值的类型,并不是我们所断言的 T,就会断言失败,但和第一种表达式不同的事,这个不会触发 panic,而是将 ok 的值设为 false ,表示断言失败,此时t 为 T 的零值。 diff --git a/source/c02/c02_04.rst b/source/c02/c02_04.rst index 673047189f8a74e54a0e5dd357ab769314b0c0fd..0ec83b2d7811fa2b3ad7dc3080616fc626d52f84 100644 --- a/source/c02/c02_04.rst +++ b/source/c02/c02_04.rst @@ -84,7 +84,7 @@ t,如果断言失败,就会触发 panic。 t, ok:= i.(T) 和上面一样,这个表达式也是可以断言一个接口对象(i)里不是 -nil,并且接口对象(i)存储的值的类型是 T,如果断言成功,就会返回其类型给 +nil,并且接口对象(i)存储的值的类型是 T,如果断言成功,就会返回其值给 t,并且此时 ok 的值 为 true,表示断言成功。 如果接口值的类型,并不是我们所断言的 diff --git a/source/c04/c04_03.md b/source/c04/c04_03.md index 7a71807421dc5ebeaa94e2797acd08968a583405..6a59a37c45c146a25774af145b55af760e916593 100644 --- a/source/c04/c04_03.md +++ b/source/c04/c04_03.md @@ -14,9 +14,6 @@ Go 语言之所以开始流行起来,很大一部分原因是因为它自带 ```go var 信道实例 chan 信道类型 - -// 定义容量为10的信道 -var 信道实例 [10]chan 信道类型 ``` 声明后的信道,其零值是nil,无法直接使用,必须配合make函进行初始化。 diff --git a/source/c04/c04_03.rst b/source/c04/c04_03.rst index 4c827d2462ea555d8ca8f45edec63d7b09a28342..5715801dce20964860a03d263741d54f77a39024 100644 --- a/source/c04/c04_03.rst +++ b/source/c04/c04_03.rst @@ -23,9 +23,6 @@ int 等等) var 信道实例 chan 信道类型 - // 定义容量为10的信道 - var 信道实例 [10]chan 信道类型 - 声明后的信道,其零值是nil,无法直接使用,必须配合make函进行初始化。 .. code:: go diff --git a/source/c04/c04_10.md b/source/c04/c04_10.md new file mode 100644 index 0000000000000000000000000000000000000000..86fe09b80c6ca377b58eccb330a6c398354885ab --- /dev/null +++ b/source/c04/c04_10.md @@ -0,0 +1,70 @@ +# 4.10 学习 Go 函数:难以理解的函数类型 + +![](http://image.iswbm.com/20200607145423.png) + +函数类型([function types](https://golang.org/ref/spec#Function_types))是一种很特殊的类型,它表示着所有拥有同样的入参类型和返回值类型的函数集合。 + +如下这一行代码,定义了一个名叫 `Greeting` 的函数类型 + +```go +type Greeting func(name string) string +``` + +这种类型有两个特征: + +1. 只接收一个参数 ,并且该参数的类型为 string +2. 返回值也只有一个参数,其类型为 string + +一个函数只要满足这些特征,那么它就可以通过如下方式将该函数转换成 Greeting 类型的函数对象(也即 greet) + +```go +func english(name string) string { + return "Hello, " + name +} + +// 转换成 Greeting 类型的函数对象 +greet := Greeting(english) +``` + +greet 做为 Greeting 类型的对象,自然也拥有 Greeting 类型的所有方法,比如下面的 say 方法 + +```go +func (g Greeting) say(n string) { + fmt.Println(g(n)) +} +``` + +直接调用试试看,并不会报错 + +```go +greet.say("World") +``` + +将上面的代码整合在一起 + +```go +package main + +import "fmt" + +// Greeting function types +type Greeting func(name string) string + +func (g Greeting) say(n string) { + fmt.Println(g(n)) +} + +func english(name string) string { + return "Hello, " + name +} + +func main() { + greet := Greeting(english) + greet.say("World") +} +// output: Hello, World +``` + + + +![](http://image.iswbm.com/20200607174235.png) \ No newline at end of file diff --git a/source/c04/c04_10.rst b/source/c04/c04_10.rst new file mode 100644 index 0000000000000000000000000000000000000000..4815d2f10626992e014b2d4a96163ab9a7b18e2f --- /dev/null +++ b/source/c04/c04_10.rst @@ -0,0 +1,76 @@ +4.10 学习 Go 函数:难以理解的函数类型 +===================================== + +|image0| + +函数类型(\ `function +types `__\ )是一种很特殊的类型,它表示着所有拥有同样的入参类型和返回值类型的函数集合。 + +如下这一行代码,定义了一个名叫 ``Greeting`` 的函数类型 + +.. code:: go + + type Greeting func(name string) string + +这种类型有两个特征: + +1. 只接收一个参数 ,并且该参数的类型为 string +2. 返回值也只有一个参数,其类型为 string + +一个函数只要满足这些特征,那么它就可以通过如下方式将该函数转换成 +Greeting 类型的函数对象(也即 greet) + +.. code:: go + + func english(name string) string { + return "Hello, " + name + } + + // 转换成 Greeting 类型的函数对象 + greet := Greeting(english) + +greet 做为 Greeting 类型的对象,自然也拥有 Greeting +类型的所有方法,比如下面的 say 方法 + +.. code:: go + + func (g Greeting) say(n string) { + fmt.Println(g(n)) + } + +直接调用试试看,并不会报错 + +.. code:: go + + greet.say("World") + +将上面的代码整合在一起 + +.. code:: go + + package main + + import "fmt" + + // Greeting function types + type Greeting func(name string) string + + func (g Greeting) say(n string) { + fmt.Println(g(n)) + } + + func english(name string) string { + return "Hello, " + name + } + + func main() { + greet := Greeting(english) + greet.say("World") + } + // output: Hello, World + +|image1| + +.. |image0| image:: http://image.iswbm.com/20200607145423.png +.. |image1| image:: http://image.iswbm.com/20200607174235.png +