首页 Golang包(模块)的组织与管理
文章
取消

Golang包(模块)的组织与管理

前言

在组织项目的过程中被坑了许久,为了日后更快从坑里爬出来,决定汇总一下今天学到的golang包、模块等结构的组织方式;

具体来说即为命名规范,包的组织,包的导入等方面;

命名规范

package

go代码中必然会存在一个关键字:package

  • package是一个包名的定义,比如我自己想写一个模块贡献给开源世界,源码必然放在一个go文件里面,现在我需要定义一个包名;
  • 假设这个包名叫superhero,现在可以package superhero
  • 我可以自行组织我的模块结构,我可以同时在两份不同的go源码中表明这两份源码是同一个包;
  • 既然是同一个包,那么这两份源码之间的可见性,遵循Go的内部规范,也就是要保证我源码A可以用源码B的函数,那么要求该函数首字母大写;

这是package关键字的用处,但是package关键字的命名规范则是:

  • 比如我的两份源码都放在目录:cs/learn/superhero,我就可以认为我这个包就叫superhero;
    • 当然,我也可以使得这两份源码属于不同的包,但是这么做没有必要,规范性不足。
  • 那么如上所述,我直接就package superhero

这就是package关键字的规范,但是记住,当后面接的是main时,具有唯一性,代表主程序的入口地址;

import

会在很多相关代码中看到形如:import "ch2/tempconv"的包导入;

显然很容易理解为一种相对路径,但是Go的内部规范不建议用相对路径,认为会增加软件管理的难度;

  • go引入了go.mod进行模块的管理,所有模块的组织都可以通过该文件来进行; 假设该文件的内容:
    1
    2
    3
    
      module GoLearn
    
      go 1.21.4
    

    module GoLearn这一行代码表明,go.mod文件所在目录下的所有包组成了一个模块,该模块名叫GoLearngo 1.21.4则表明了使用的go版本;

  • 因此,import "ch2/tempconv"表示的应该是,在ch2模块下的包tempconv

官方同时留了一个临时方案,就是在go.mod中通过replace关键字来解决一些特殊需求下的相对路径导入的问题;

包的组织

Golang中所有模块的组织,管理都是通过go.mod文件来进行的;

仍然以举的例子superhero来说明,一般而言,一个模块下都会需要有一个go.mod

  • 注意,这是一个模块,而不是包,一个模块中可以包含多个包,而我们可以认为一个模块就是一个文件夹;
  • 一个文件夹下可以有很多个子文件夹,可以对应理解为有很多个包。
  • 命令go mod init <Your Module Name>
    • go mod init GoLearn,会在执行该命令的文件夹处(一般可以立即为工作区)生成一份go.mod文件,该文件内容大致为:
      1
      2
      3
      
        module GoLearn
      
        go 1.21.4
      
    • GoLearn即为模块名,可以理解为寻找包的一个入口;

到这里,我们的模块写好了。

  • 假设目录结构是
      ├── moduledemo
      │   ├── moduledemo1.go
      │   └── moduledemo2.go
      └── superhero
          ├── superhero1.go
          └── superhero2.go
    
  • 现在我在我的工作区写了一份go源码main.go,需要调用moduledemo以及superhero包,假设工作区对应的模块名为GoLearn
    • 只需要如此import,那么两个包就被导入main.go,接下来继续调用即可。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
        package main
        import (
            "GoLearn/moduledemo"
            "GoLearn/superhero"
        )
      
        func main() {
            moduledemo.moduledemo_func()
            superhero.superhero_func()
        }
      
  • 完成

包的导入

单独起一节是因为碰到了这么一个问题:

import中导入了一个模块之后,代码运行没问题,编译没问题,但是vscode提示” no required module provides package “ch2/tempconv” “

也就是在编译器层面我的包正常导入且没有任何问题,但是vscode提示问题;

直到最后在main.go目录下的go.mod文件中加入replace ch2/tempconv => "./ch2/tempconv"之后vscode也不报问题了;

  • 猜想是因为ch2/tempconv正好与main.go go.mod在同一个目录下,如果是需要返回到上一级目录去找模块估计编译运行都会出问题了,因为./一般可以默认,../则不是;
  • 我猜的;

其实只要按照Go官方推荐的方式进行包的组织与管理就好了。

2024年6月16日更新:在Golang中,如果一个文件名形式为:`XX_test.go`,那么这个包内的函数在外界引用时会提示未定义.....
本文由作者按照 CC BY 4.0 进行授权

Go的复合数据类型

Go函数