zoukankan      html  css  js  c++  java
  • Go语言--第8章 包(package)

    第8章 包(package)

    8.1 工作目录

    GOPATH是go语言使用的一个环境 变量,使用绝对路径

    8.1.1 命令行查看GOPATH信息

    go env
    

    显示go开发环境配置信息:

    $ go env
    // 表示目标处理器架构
    GOARCH="amd64"
    //表示编译器和链接器的安装位置
    GOBIN=""
    GOCACHE="/Users/jihan/Library/Caches/go-build"
    GOEXE=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="darwin"
    //目标操作系统
    GOOS="darwin"
    //当前工作目录
    GOPATH="/Users/jihan/go"
    GOPROXY=""
    GORACE=""
    //GO开发包安装目录
    GOROOT="/usr/local/go"
    GOTMPDIR=""
    GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
    GCCGO="gccgo"
    CC="clang"
    CXX="clang++"
    CGO_ENABLED="1"
    GOMOD=""
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/vm/zby04lq56tg1y08qs5c6kkq80000gn/T/go-build459742728=/tmp/go-build -gno-record-gcc-switches -fno-common"
    

    GOPATH在不同平台上的安装路径

    平台 GOPATH默认值 举例
    Window平台 %USERPROFILE%/go C:Users用户名go
    Uninx平台 $HOME/go /home/用户名/go

    8.1.2 使用GOPATH的工程结构

    GOPATH工作目录下,代码保存在$GOPATH/src目录

    通过go buildgo installgo get等命令,将产生二进制可执行文件放在(GOPATG/bin目录**下,生成中间缓存文件保存放在**)GOPATG/pkg目录

    若需要将整个源码添加到版本控制工具中,只需将$GOPATH/src目录源码添加即可

    8.1.3 设置和使用GOPATH

    1. 设置当前工作目录为GOPATH
    2. 建立GOPATH中源码目录
    3. 添加main.go源码文件
    4. 编译源码并运行

    以下示例为linux平台操作

    设置当前工作目录为GOPATH

    export GOPATH=path
    

    例如:

    GOPATH="/Users/jihan/go"

    export GOPATH=/Users/jihan/go
    

    建立GOPATH中源码目录

    mkdir -p src/hello
    

    添加main.go源码文件

    创建$GOPATH/src/main.go

    package main
    import "fmt"
    func main() {
      fmt.Println("hello")
    }
    

    编译源码并运行

    go install hello
    

    编译完可执行文件会保存在$GOPATH/bin目录下

    ./hello //进行执行
    

    8.2 创建包package -- 编写自己的代码扩展

    包要求在目录下的所有文件的第一行添加

    package 包名
    

    特性:

    • 一个目录下的同级文件归属一个包
    • 包名可以与目录不同名
    • 包名为main的包为应用程序入口包,编译源码没有main包时,将无法编译输出可执行文件

    8.3 导出标识符 -- 让外部访问包的类型和值

    如果一个包引用另一个包的标识符(类型、变量、 常量时)必须首先将被引用的标识符导出

    package mypkg
    var myVar = 100
    const myConst = "go"
    type myStruct struct {}
    

    将myStruct和myConst首字母大写,导出这些标识符

    package mypkg
    var MyVar = 100
    const MyConst = "go"
    type MyStruct struct {}
    

    导出结构体及接口成员

    结构体和接口成员同样字段或方法首字母大写,外部可以访问

    type MyStruct struct {
      //包外可以访问的字段
      ExportField int
    }
    

    8.4 导入包(import) -- 在代码中使用其他的代码

    使用import关键字,导入包包名使用双引号包围

    8.4.1默认导入写法

    1. 单行导入

      import "包1"
      import "包2"
      
    2. 多行导入

      import (
      	"包1"
      	"包2"
      ) 
      

    导入包例子

    importadd/mylib/add.go

    package mylib
    
    func Add(a, b int) int {
    	return a + b
    }
    

    eight/8.4/main.go

    package main
    import (
      // 文件目录相对GOPATH的相对路径
    	"../../eight/8.4/mylib"
    	"fmt"
    )
    func main() {
    	fmt.Println(mylib.Add(1, 2))
    }
    

    8.4.2 自定义命名导入包名

    格式

    customName "path	opackage"
    
    • path/to/package 导入包路径

    • customName 自定义包名

    package main
    import (
    	renameMylib "../../eight/8.4/mylib"
    	"fmt"
    )
    func main() {
    	fmt.Println(renameMylib.Add(1, 2))
    }
    

    8.4.3 匿名导入包 -- 只导入包但不适用包内类型和数值

    package main
    import (
    	_ "../../eight/8.4/mylib"
    	"fmt"
    )
    func main() {
    	// fmt.Println(renameMylib.Add(1, 2))
    }
    

    8.4.4 包在程序启动前的初始化入口:init

    特性:init()函数

    • 每个源码可以食欲哦那个1个init()函数

    • init()会在程序执行前(main()函数执行前)被自动调用

    • 调用顺序为main()中引用的包,以深度优先顺序初始化

      例如:包引用关系 main -> A->B->C 调用顺序为:c.init->B.init->A.init->main

    • 同一个包的多个init()函数调用顺序不可以预期

    • init()不能憋其他函数调用

    8.4.5 理解包导入后的init()函数初始化顺序

    go语言包会从main包开始检查其所有引用所有包,每个包也可能包含其他的包

    go编译器由此构建一个树状的包引用关系,在根据引用顺序决定编译顺序,依次编译这些包的代码

    在运行时,被最后导入的包会最先初始化并调用init()函数

    例子:

    文件目录:

    .../eight/8.4.5
    .../eight/8.4.5/pkginit
    .../eight/8.4.5/pkginit/pkg1
    .../eight/8.4.5/pkginit/pkg1/pkg1.go
    .../eight/8.4.5/pkginit/pkg2
    .../eight/8.4.5/pkginit/pkg2/pkg2.go
    .../eight/8.4.5/pkginit/main.go
    

    .../eight/8.4.5/pkginit/main.go

    package main
    import (
    	"../../../eight/8.4.5/pkginit/pkg1"
    )
    func main()  {
    	pkg1.ExecPkg1()
    }
    

    .../eight/8.4.5/pkginit/pkg1/pkg1.go

    package pkg1
    
    import(
    	"../../../../eight/8.4.5/pkginit/pkg2"
    	"fmt"
    )
    func ExecPkg1()  {
    	fmt.Println("ExecPkg1")
    	pkg2.ExecPkg2()
    }
    func init()  {
    	fmt.Println("pkg1  init")
    }
    

    .../eight/8.4.5/pkginit/pkg2/pkg2.go

    package pkg2
    
    import(
    	"fmt"
    )
    func ExecPkg2()  {
    	fmt.Println("ExecPkg2")
    }
    func init()  {
    	fmt.Println("pkg2  init")
    }
    

    运行结果:

    pkg2 init
    pkg1 init
    ExecPkg1
    ExecPkg2

    8.5 示例:工厂模式自动注册--管理过个包的结构体

    利用包init()函数特性,将cls1和cls2两个包注册到工厂,使用字符串创建这两个注册好的结构实例

    $HOME:src目录路径

    目录结构:

    $HOME/eight/8.5
    $HOME/eight/8.5/clsfactory
    $HOME/eight/8.5/clsfactory/base
    $HOME/eight/8.5/clsfactory/base/factory.go
    $HOME/eight/8.5/clsfactory/cls1
    $HOME/eight/8.5/clsfactory/cls1/reg.go
    $HOME/eight/8.5/clsfactory/cls2
    $HOME/eight/8.5/clsfactory/cls2/reg.go
    $HOME/eight/8.5/clsfactory/main.go
    

    $HOME/eight/8.5/clsfactory/base/factory.go

    package base
    // 类接口
    type Class interface {
    	Do()
    }
    // 声明保存工厂信息变量
    var (
    	factoryByName = make(map[string]func() Class)
    )
    // 注册一个类生成工厂
    func Register(name string, factory func() Class)  {
    	factoryByName[name] = factory
    }
    
    // 根据名称创建对应的类
    func Create(name string) Class  {
    	if f, ok := factoryByName[name]; ok {
    		return f()
    	} else {
    		panic("name not found")
    	}
    }
    

    $HOME/eight/8.5/clsfactory/cls1/reg.go

    package cls1
    
    import (
    	"../../../../eight/8.5/clsfactory/base"
    	"fmt"
    )
    
    // 定义类1
    type Class1 struct {
    
    }
    // 实现Class接口
    func (c  *Class1) Do() {
    	fmt.Println("Class1")
    }
    
    func init()  {
    	// 在启动时注册类1的工厂
    	base.Register("Class1", func() base.Class {
    		return new (Class1)
    	})
    }
    

    $HOME/eight/8.5/clsfactory/cls2/reg.go

    package cls2
    
    import (
    	"../../../../eight/8.5/clsfactory/base"
    	"fmt"
    )
    
    // 定义类2
    type Class2 struct {
    
    }
    // 实现Class接口
    func (c  *Class2) Do() {
    	fmt.Println("Class2")
    }
    
    func init()  {
    	// 在启动时注册类1的工厂
    	base.Register("Class2", func() base.Class {
    		return new (Class2)
    	})
    }
    

    $HOME/eight/8.5/clsfactory/main.go

    package main
    
    import(
    	"../../../eight/8.5/clsfactory/base"
    	_ "../../../eight/8.5/clsfactory/cls1"
    	_ "../../../eight/8.5/clsfactory/cls2"
    )
    
    func main()  {
    	// 根据字符串动态创建一个Class1的实例
    	c1 := base.Create("Class1")
    	c1.Do()
    	// 根据字符串动态创建一个Class2的实例
    	c2 := base.Create("Class2")
    	c2.Do()
    }
    

    运行结构:

    Class1
    Class2

  • 相关阅读:
    std::async
    k最近邻算法(kNN)
    QNX下进程间通信
    ubuntu 18.04 安装破解pycharm professional 专业版
    安装scrapy出现Twisted依赖问题
    pytorchhub解决bug:.cache orchhubmaster.zip.....'另一个程序正在使用此文件,进程无法访问。'
    pytorchhub教程之安装pytorch或pytorchversion
    错误:java.lang.ClassNotFoundException:org.apache.commons.fileupload.FileItemFactory 解决方案
    Failed to start component [StandardEngine[Catalina].StandardHost[localhost].错误解决方案
    Javaweb之注解访问servlet和web.xml配置文件
  • 原文地址:https://www.cnblogs.com/smallyi/p/12684478.html
Copyright © 2011-2022 走看看