【go从入门到精通】go包,内置类型和初始化顺序

news2024/11/15 21:56:02

        大家好,这是我给大家准备的新的一期专栏,专门讲golang,从入门到精通各种框架和中间件,工具类库,希望对go有兴趣的同学可以订阅此专栏。

go基础 。

Go文件名:

      所有的go源码都是以 ".go" 结尾,不过我们有时候为了支持多平台,多版本,或者在不同的平台,CPU下做不同的逻辑处理,我们对go的文件名的命名方式又有一些要求:

1、平台区分
文件名_平台。
例: file_windows.go, file_unix.go
可选为:windows, unix, posix, android, bsd, solaris, linux等

2、测试单元
文件名test.go或者 文件名平台_test.go。
例: path_test.go, path_windows_test.go

3、版本区分(猜测)
文件名_版本号等。
例:point_windows_1.4.go

4、CPU类型区分, 汇编用的多
文件名_(平台:可选)_CPU类型.
例:point_linux_amd64.go
可选:amd64, none, 386, arm, arm64, x86等。

Go语言命名和关键字 

1.Go的函数、变量、常量、自定义类型、包(package)的命名方式遵循以下规则:

    1)首字符可以是任意的Unicode字符或者下划线
    2)剩余字符可以是Unicode字符、下划线、数字
    3)字符长度不限

2.Go只有25个关键字

    break        default      func         interface    select
    case         defer        go           map          struct
    chan         else         goto         package      switch
    const        fallthrough  if           range        type
    continue     for          import       return       var

3.Go还有37个保留字

    Constants:    true  false  iota  nil

    Types:    int  int8  int16  int32  int64  
              uint  uint8  uint16  uint32  uint64  uintptr
              float32  float64  complex128  complex64
              bool  byte  rune  string  error

    Functions:   make  len  cap  new  append  copy  close  delete
                 complex  real  imag
                 panic  recover

Go语言声明:

go有四种主要声明方式:

    var(声明变量), const(声明常量), type(声明类型) ,func(声明函数)。

Go的程序是保存在多个.go文件中,文件的第一行就是 package(包名) 声明,用来说明该文件属于哪个包(package),package声明下来就是import声明,再下来是类型,变量,常量,函数的声明。

        go是使用包来组织源代码的,包是多个go源码的集合,是一种高级的代码复用方案。golang为我们提供了很多内置的包,如 fmt、os、io 等。

        任何源代码文件必须属于某个包,同时源码文件的第一行有效代码必须是package pacakgeName 语句,通过该语句声明自己所在的包。

         正如我们上一篇文章写的最简单的hello world程序输出一样:

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

         我们在文件的最开始是通过package  main的方式来说明该文件属于main包,接下来我们需要知道包是什么,怎么使用它(其实学过java,或者python等语言的对包的概念和使用并不陌生)

包的基本概念

        Go 的包借助了目录树组织形式,一般包的名称就是其源文件所在的目录,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰。

包可以定义在很深的目录中,包名的定义是不包括目录路径的,但是包在引用时一般使用全路径引用。比如在GOPATH/src/a/b/ 下定义一个包 c。在包 c 的源码中只需声明为package c,而不是声明为package a/b/c,但是在导入 c 包时,需要带上路径,例如import “a/b/c”。

包的习惯用法:

  • 包名一般是小写的,使用一个简短且有意义的名称。
  • 包名一般要和所在的目录同名,也可以不同,包名中不能包含- 等特殊符号。
  • 包一般使用域名作为目录名称,这样能保证包名的唯一性,比如 GitHub 项目的包一般会放到GOPATH/src/github.com/userName/projectName 目录下。
  • 包名为 main 的包为应用程序的入口包,编译不包含 main 包的源码文件时不会得到可执行文件。
  • 一个文件夹下的所有源码文件只能属于同一个包,同样属于同一个包的源码文件不能放在多个文件夹下。

包的导入

要在代码中引用其他包的内容,需要使用 import 导入使用的包。具体语法如下:

import "包的路径"

注意事项:

  • import 导入语句通常放在源码文件开头包声明语句的下面;
  • 导入的包名需要使用双引号包裹起来;
  • 包名是从GOPATH/src/ 后开始计算的,使用/ 进行路径分隔。

包的导入有两种写法,分别是单行导入和多行导入。

单行导入

import "package1"
import "package2"

多行导入

import (
    "package1"
    "package2"
)

在使用习惯和代码的可读性上,我们都习惯于使用多行导入更方便于我们管理使用。 

包的导入路径

包的引用路径有两种写法,分别是全路径导入和相对路径导入

包的引用格式

包的引用有四种格式,下面以 fmt 包为例来分别演示一下这四种格式。

1) 标准引用格式

import "fmt"

此时可以用fmt.作为前缀来使用 fmt 包中的方法,这是常用的一种方式。

示例代码如下:

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

2) 自定义别名引用格式

在导入包的时候,我们还可以为导入的包设置别名,如下所示:

import F "fmt"

 其中 F 就是 fmt 包的别名,使用时我们可以使用F.来代替标准引用格式的fmt.来作为前缀使用 fmt 包中的方法。

示例代码如下:

package main
import F "fmt"
func main() {
    F.Println("Hello world")
}

3) 省略引用格式

import . "fmt"

这种格式相当于把 fmt 包直接合并到当前程序中,在使用 fmt 包内的方法是可以不用加前缀fmt.,直接引用。

示例代码如下:

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

4) 匿名引用格式

在引用某个包时,如果只是希望执行包初始化的 init 函数,而不使用包内部的数据时,可以使用匿名引用格式,如下所示:

import _ "fmt"

匿名导入的包与其他方式导入的包一样都会被编译到可执行文件中。

使用标准格式引用包,但是代码中却没有使用包,编译器会报错。如果包中有 init 初始化函数,则通过import _ “包的路径” 这种方式引用包,仅执行包的初始化函数,即使包没有 init 初始化函数,也不会引发编译器报错。

示例代码如下:

package main
import (
    _ "github.com/astaxie/beego"
    "fmt"
)
func main() {
    fmt.Println("Hello world")
}

注意:

  • 一个包可以有多个 init 函数,包加载时会执行全部的 init 函数,但并不能保证执行顺序,所以不建议在一个包中放入多个 init 函数,将需要初始化的逻辑放到一个 init 函数里面。
  • 包不能出现环形引用的情况,比如包 a 引用了包 b,包 b 引用了包 c,如果包 c 又引用了包 a,则编译不能通过。
  • 包的重复引用是允许的,比如包 a 引用了包 b 和包 c,包 b 和包 c 都引用了包 d。这种场景相当于重复引用了 d,这种情况是允许的,并且 Go 编译器保证包 d 的 init 函数只会执行一次。

 这块大家可以多练习练习尝试下,凡是和语言相关的知识在初步学习过程中要不断地练习和尝试,就会有不一样的角度的理解。

包的初始化顺序

在分享包的初始化顺序之前,有必要了解下init函数和main函数, 

init函数

go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性。

有下面的特征:

    1 init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等

    2 每个包可以拥有多个init函数

    3 包的每个源文件也可以拥有多个init函数

    4 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)

    5 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序

    6 init函数不能被其他函数调用,而是在main函数执行之前,自动被调用

main函数

   Go语言程序的默认入口函数(主函数):func main()
    函数体用{}一对括号包裹。



    func main(){
        //函数体
    }

init函数和main函数的异同

    相同点:
        两个函数在定义时不能有任何的参数和返回值,且Go程序自动调用。
    不同点:
        init可以应用于任意包中,且可以重复定义多个。
        main函数只能用于main包中,且只能定义一个。

两个函数的执行顺序:

对同一个go文件的init()调用顺序是从上到下的。

对同一个package中不同文件是按文件名字符串比较“从小到大”顺序调用各文件中的init()函数。

对于不同的package,如果不相互依赖的话,按照main包中”先import的后调用”的顺序调用其包中的init(),如果package存在依赖,则先调用最早被依赖的package中的init(),最后调用main函数。

为了进一步看下init函数和main函数的初始化顺序,我们可以看下这段代码:

package main

import (
	"fmt"
)
const (
	CFG_VISIT       = "visit.json"
)

var (
	gameStatus = 0
)

func init(){
	fmt.Println("go init")
}

func main(){
    fmt.Println("hello world")
}

对于import 包,const 初始化, var初始化,init函数,main函数的调用顺序是什么样的?

实际上,整个程序的执行流程可以用下面的图来表示:


总结下来,go语言包的初始化有如下特点:

  • 包初始化程序从 main 函数引用的包开始,逐级查找包的引用,直到找到没有引用其他包的包,最终生成一个包引用的有向无环图。
  • golang编译器会将有向无环图转换为一棵树,然后从树的叶子节点开始逐层向上对包进行初始化。
  • 单个包的初始化过程如上图所示,先初始化常量,然后是全局变量,最后执行包的 init 函数。

内置类型

值类型:

    bool
    int(32 or 64), int8, int16, int32, int64
    uint(32 or 64), uint8(byte), uint16, uint32, uint64
    float32, float64
    string
    complex64, complex128
    array    -- 固定长度的数组

引用类型:(指针类型)

    slice   -- 序列数组(最常用)
    map     -- 映射
    chan    -- 管道

内置函数

Go 语言拥有一些不需要进行导入操作就可以使用的内置函数。它们有时可以针对不同的类型进行操作,例如:len、cap 和 append,或必须用于系统级的操作,例如:panic。因此,它们需要直接获得编译器的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1483882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

latex宏包pythontex使用简明手册

文章目录 1.背景2. 基本示例2.1 hello world2.1.1 代码与输出结果2.1.2 说明2.1.3 如何编译使用了pythontex宏包的Latex文档2.1.4 如何既输出python代码又输出代码执行结果 2.2 在Latex中嵌入python变量的值2.2.1 示例代码与文档输出2.2.2 说明 2.3 在latex文档中输出控制台会话…

2.29号的复盘开始商城项目的规格如何设施的方式

第五次设计方式 我本来想的是,按照对于的组方式解拆分,通过分组处理的内存不同查询对应的手机上 出现问就是这里 对于的组相应规格相应里面有对于的价格,价格也就相同,无法进行区分 查询出来的对应的结果 还是没有办法具体拆分…

现货大宗商品发售平台搭建须知

在搭建现货大宗商品发售平台时,需要考虑以下关键因素: 目标市场分析:首先要明确你的平台将服务于哪些大宗商品市场,如农产品、金属、能源等。了解这些市场的特点、参与者、交易规则等,有助于你设计出更符合市场需求的…

解析/区分MOS管的三个引脚G、S、D(NMOS管和PMOS管)

MOS管的三个引脚分别是Gate(栅极)、Source(源极)和Drain(漏极)。以下是详细介绍: Gate(栅极)。这是控制MOS管开关的关键引脚,用于控制电流的流通。Source&…

pikachu验证XXE漏洞

先随便输入一个内容查看 接下来用bp抓包看下参数 有个xml参数&#xff0c;而且Content-Type: application/x-www-form-urlencoded&#xff0c;我们传入url编码后的xml内容试一下 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE foo [<!EN…

社区店选址人流量标准:如何确保充足的顾客流量

在选择社区店的位置时&#xff0c;确保充足的顾客流量是至关重要的。 作为一名开鲜奶吧5年的创业者&#xff0c;我将分享一些关于社区店选址人流量标准的关键要点&#xff0c;帮助你找到最适合的店铺位置。 1、研究人口统计学数据 了解潜在顾客的人口特征是选址的基础。通过研…

Unity3D学习之Lua热更新解决方案(二)XLua

文章目录 1 XLua概述2 xLua导入和AB包相关准备3 C#调用Lua3.1 Lua解析器3.2 文件加载重定向3.3 Lua解析器管理器3.3.1 重定向AB包内的Lua3.3.2 获得_G大表 3.4 全局变量的获取3.5 全局函数的获取3.5.1 无参无返回3.5.2 有参有返回3.5.3 多返回值3.5.4 变长参数 3.6 List和Dicti…

C 嵌入式系统设计模式 18:临界区模式

本书的原著为&#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》&#xff0c;讲解的是嵌入式系统设计模式&#xff0c;是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述嵌入式并发和资源管理模式之四…

【AIGC】OpenAI推出王炸级模型sora,颠覆AI视频行业(2024)

对于OpenAI推出的Sora模型&#xff0c;我们可以进一步探讨其可能的技术细节、潜在应用以及对AI视频行业的影响。 点击以下任一云产品链接&#xff0c;跳转后登录&#xff0c;自动享有所有云产品优惠权益&#xff1a; 经过笔者亲测&#xff0c;强烈推荐腾讯云轻量应用服务器作…

前端打包部署(黑马学习笔记)

我们的前端工程开发好了&#xff0c;但是我们需要发布&#xff0c;那么如何发布呢&#xff1f;主要分为2步&#xff1a; 1.前端工程打包 2.通过nginx服务器发布前端工程 前端工程打包 接下来我们先来对前端工程进行打包 我们直接通过VS Code的NPM脚本中提供的build按钮来完…

Http基础之http协议、无状态协议、状态码、http报文、跨域-cors

Http基础 HTTP基础HTTP协议请求方法持久连接管线化 无状态协议使用Cookie状态管理 状态码1XX2XX OK200 OK204 NO Content206 Content-Range 3XX 重定向301302304307 4XX400401403404 5XX500503 HTTP报文请求报文响应报文通用首部字段Cache-ControlConnectionDate请求首部字段Ac…

Python编程小案例—利用flask查询本机IP归属并输出网页图片

Python编程小案例—利用flask查询本机IP归属并输出网页图片 环境&#xff1a;Pycharm Mac OS 源码如下&#xff1a; from flask import Flask, render_template, requestapp Flask(__name__)app.route(/) def index():return render_template(IP查询.html)if __name__ __…

还在用Jenkins?快来试试这款简而轻的自动部署软件!

最近发现了一个比 Jenkins 使用更简单的项目构建和部署工具&#xff0c;完全可以满足个人以及一些小企业的需求&#xff0c;分享一下。 Jpom 是一款 Java 开发的简单轻量的低侵入式在线构建、自动部署、日常运维、项目监控软件。 日常开发中&#xff0c;Jpom 可以解决下面这些…

STM32 DMA入门指导

什么是DMA DMA&#xff0c;全称直接存储器访问&#xff08;Direct Memory Access&#xff09;&#xff0c;是一种允许硬件子系统直接读写系统内存的技术&#xff0c;无需中央处理单元&#xff08;CPU&#xff09;的介入。下面是DMA的工作原理概述&#xff1a; 数据传输触发&am…

venv、pip、conda、anaconda、miniconda的区别和优缺点,和彻底清除python多余的环境

virtualenv(venv) 这是一个虚拟环境管理器&#xff0c;它可以让你每个项目甚至每个脚本配置一个自定义的Python解释器环境&#xff0c;这最大的好处是我可以不污染开发环境。​ pip pip 是 Python 最常用的包管理器&#xff0c;它能自动处理依赖 。 conda 如果说venv是虚拟…

5、DVWA代码审计(2)

一、csrf 1、csrf(low) 限制 复现 GET /vulnerabilities/csrf/?password_new123456&password_conf123456&ChangeChange HTTP/1.1 Host: ddd.com Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,…

探索数据宇宙:深入解析大数据分析与管理技术

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

迪杰斯特拉算法的具体应用

fill与memset的区别介绍 例一 #include <iostream> #include <algorithm> using namespace std; const int maxn500; const int INF1000000000; bool isin[maxn]{false}; int G[maxn][maxn]; int path[maxn],rescue[maxn],num[maxn]; int weight[maxn]; int cityn…

Linux内存地址空间

目录 一、虚拟地址空间 1.虚拟地址空间的定义 2.虚拟地址空间的布局 二、内存壁垒 1.内存壁垒的定义​编辑 2.段错误 三、内存映射的建立与解除 &#xff08;1&#xff09;mmap &#xff08;2&#xff09;munmap &#xff08;3&#xff09;堆内存的分配和释放 1.sbrk …

一文掌握大模型提示词技巧:从战略到战术

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…