Go语言核心36讲

Posted it-chen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言核心36讲相关的知识,希望对你有一定的参考价值。

Go语言核心36讲

其它学习课程目录:

其它学习课程目录:

从0开始学微服务

面试官绝杀:系统是如何支撑高并发的?

分布式技术原理与算法解析

消息队列高手课

从0开始学架构

微服务架构实战160讲

网络编程实战

01 | 工作区和GOPATH

 

gopath指的是工作空间(包括源码,可以有多个)

 

构建使用命令go build,安装使用命令go install。构建和安装代码包的时候都会执行编译、打包等操作,并且这些操作生成的任何文件都会先被保存到某个临时的目录中。

 

go install命令安装的是库源码文件时会产生归档文件,结果文件会被搬运到它所在工作区的 pkg 目录下的某个子目录

go install命令安装的是命令源码文件,那么结果文件会被搬运到它所在工作区的bin 目录中,或者环境变量GOBIN指向的目录中。

 

go build可以没有命令源码文件,构建命令源码文件时候,生成的可执行文件文件名会与文件所在目录的名字一样

在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包。当然,如果被依赖的代码包的归档文件不存在,

或者源码文件有了变化,那它还是会被编译。

当有多个文件时,go build必须一起构建

 

下载包命令 : go get

go get 虽然简单粗暴,但是缺点是不能进行版本控制

 

思考题

Go 语言在多个工作区中查找依赖包的时候是以怎样的顺序进行的?

如果在多个工作区中都存在导入路径相同的代码包会产生冲突吗?

 

02 | 命令源码文件

1.源码文件分为三种:命令源码文件(有main方法)、库源码文件和测试源码文件

2.编写命令源码文件的关键包: flag。

代码

    package main
     
    import (
        "fmt"
        "flag"
    )
     
    var name  string
     
    func init()  {
        //函数flag.StringVar接受 4 个参数。第 1 个是接收命令参数值的地址,第二个是命令参数的名称
        //第三个是当命令参数没值时候的默认值   第四个是该命令参数的简单说明
        flag.StringVar(&name,"name","everyone","The greeting object.")
        //var name = flag.String("name", "everyone", "The greeting object.")
    }
     
    func main()  {
        //解析命令参数,并把它们的值赋给相应的变量。
        flag.Parse()
        fmt.Printf("hello,%s
",name)
    }

运行结果

技术图片
用help查看参数说明

图片第二行的路径是命令构建上述命令源码文件时临时生成的可执行文件的完整路径

 技术图片

思考题

默认情况下,我们可以让命令源码文件接受哪些类型的参数值?

我们可以把自定义的数据类型作为参数值的类型吗?如果可以,怎样做?

 

03 | 库源码文件

在同一目录下的源码文件  都必须声明属于同一个包(比如你在一个文件夹下创建了一个命令源码文件,该文件夹下其他的所有go文件都必须声明为main包)

源码文件声明的包名可以与其所在目录名称不同,但是同一目录下的源码文件 必须声明同样的包名

 技术图片

可以看到,当引用别的目录的源码文件时,导入的包路径为文件夹的名字(既other,该路径是相对于src的路径),而调用的时候却是通过包名来调用(other1)

注意

当需要运行上面代码时,只需要go run main.go

技术图片

如果上图的main方法里调用的是yasuo包里的Hello()方法时,则需要go run 两个文件,如下图,否则就会报错

undefined: Hello

或者是>go build go36/day3/yasuo(src的相对路径)

技术图片

原因是因为前面是引入了代码包,所有run的时候,可以通过路径找到对应的文件,然后编译构建运行,后面报错是因为找不到库源码文件,因为没指定(我猜的)

 

模块级私有internal的使用姿势

 

思考题

如果你需要导入两个代码包,而这两个代码包的导入路径的最后一级是相同的,比如:dep/lib/flag和flag,那么会产生冲突吗?

如果会产生冲突,那么怎样解决这种冲突,有几种方式?

1.import后路径最后一级相同,不一定会冲突。
分为两种情况:
a.如果文件夹下文件声明的包名相同,则肯定冲突,会报错redeclared。
b.如果文件夹下文件声明的包名不同,也不会冲突。
 

2.如果冲突,我能想到的解决方式:
a.给包设置别名,调用的时候来区分开不同的package,比如:import(b "bbbb")

b.导入的点操作,import(. "bbbb")。这样就可以直接调用bbbb下面的函数而不用再bbbb.funcname的方式调用。

c.如果只是想引入某包并没有在代码中实际调用则可以这么处理来避免冲突:import(_ "bbbb")

d.采取不同的包名声明

 

 

04 | 程序实体的那些事儿(上)

var name = 1

name := 1(短变量声明)

短变量声明只能在函数体内部使用短变量声明。

 技术图片

技术图片

 

 

05 | 程序实体的那些事儿(中)

 

如果我们把代码包导入语句写成import . XXX的形式(注意有个.),那么就会让这个“XXX”包中公开的程序实体被当前源码文件中的代码,视为当前代码包中的程序实体

 

变量重声明是对同一个变量的多次声明,这里的变量只有一个。而可重名变量中涉及的变量肯定是有多个的。

不论对变量重声明多少次,其类型必须始终一致,具体遵从它第一次被声明时给定的类型。而可重名变量之间不存在类似的限制,它们的类型可以是任意的。

如果可重名变量所在的代码块之间存在直接或间接的嵌套关系,那么它们之间一定会存在“屏蔽”的现象。但是这种现象绝对不会在变量重声明的场景下出现。
技术图片

技术图片技术图片
 

 

 


以上是关于Go语言核心36讲的主要内容,如果未能解决你的问题,请参考以下文章

Go语言核心36讲(Go语言进阶技术十六)--学习笔记

Go语言核心36讲(Go语言进阶技术七)--学习笔记

你知道的Go切片扩容机制可能是错的

Go36-15-指针

Go36-26-互斥锁与读写锁

Go36-3-代码包