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

        大家好,这是我给大家准备的新的一期专栏,专门讲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    selectcase         defer        go           map          structchan         else         goto         package      switchconst        fallthrough  if           range        typecontinue     for          import       return       var

3.Go还有37个保留字

    Constants:    true  false  iota  nilTypes:    int  int8  int16  int32  int64  uint  uint8  uint16  uint32  uint64  uintptrfloat32  float64  complex128  complex64bool  byte  rune  string  errorFunctions:   make  len  cap  new  append  copy  close  deletecomplex  real  imagpanic  recover

Go语言声明:

go有四种主要声明方式:

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

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

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

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

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

package mainimport "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 mainimport ("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 函数。

内置类型

值类型:

    boolint(32 or 64), int8, int16, int32, int64uint(32 or 64), uint8(byte), uint16, uint32, uint64float32, float64stringcomplex64, complex128array    -- 固定长度的数组

引用类型:(指针类型)

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

内置函数

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Java 探索者之路] 一个大厂都在用的分布式任务调度平台

分布式任务调度平台是一种能够在分布式计算环境中调度和管理任务的系统,在此环境下,各个任务可以在独立的节点上运行。它有助于提升资源利用率,增强系统扩展性以及提高系统对错误的容忍度。 文章目录 1. 分布式任务调度平台1. 基本概念1.1 任…

CVPR2023 | 提升图像去噪网络的泛化性,港科大上海AILab提出 MaskedDenoising,已开源!

作者 | 顾津锦 首发 | AIWalker 链接 | https://mp.weixin.qq.com/s/o4D4mNM3jL6sYuhUC6VgoQ 当前深度去噪网络存在泛化能力差的情况,例如,当训练集噪声类型和测试集噪声类型不一致时,模型的性能会大打折扣。作者认为其原因在于网络倾向于过度…

数据结构与算法学习【算法思想之二分法基础】

文章目录 数据结构与算法学习【算法思想之二分查找基础】本文学习目标或巩固的知识点 最基础的二分查找🟢通过题目可知题解结果验证 数据结构与算法学习【算法思想之二分查找基础】 本文学习目标或巩固的知识点 学习二分法类题目 巩固基础的二分法 提前说明&#…

git根据文件改动将文件自动添加到缓冲区

你需要修改以下脚本中的 use_cca: false 部分 #!/bin/bash# 获取所有已修改但未暂存的文件 files$(git diff --name-only)for file in $files; do# 检查文件中是否存在"use_cca: false"if grep -q "use_cca: false" "$file"; thenecho "Ad…

matplotlib从起点出发(14)_Tutorial_imshow_origin_extent

0 总述 imshow()允许你将图像(将进行颜色映射——基于norm和cmap——的2D数组或将按原样使用的3D RGB(A)的数组)渲染到数据空间中的矩形区域。最终渲染中图像的方向由原点和范围关键字参数(以及生成的AxesImage实例上的属性)和Ax…

复合机器人是一种集成了移动机器人

复合机器人是一种集成了移动机器人、协作机器人和机器视觉等多项功能的新型机器人。它的开发目的是为了解决工厂物流中最后一米的问题,提供智能搬运解决方案。复合机器人不仅集成了自主移动机器人(AMR)、机械臂等工作单元,还使用了…

Springboot+vue的高校教师教研信息填报系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频: Springbootvue的高校教师教研信息填报系统(有报告)。Javaee项目,springboot vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller&am…

TypeScript08:在TS中使用模块化

前言:tsconfig.json中的配置 一、前端领域中的模块化标准 前端领域中的模块化标准有: ES6、commonjs、amd、umd、system、esnext 二、 TS中如何书写模块化语句 TS 中,导入和导出模块,统一使用 ES6 的模块化标准。 myModule.ts &a…

k8s-kubeapps图形化管理 21

结合harbor仓库 由于kubeapps不读取hosts解析,因此需要添加本地仓库域名解析(dns解析) 更改context为全局模式 添加repo仓库 复制ca证书 添加成功 图形化部署 更新部署应用版本 再次进行部署 上传nginx 每隔十分钟会自动进行刷新 在本地仓库…

云主机和传统主机到底有什么区别呢?

随着信息技术的快速发展,企业对IT基础设施的要求越来越高,许多问题等待解决:政府传统部署扩容升级麻烦、公司服务器维护周期长、建设和维护成本低等。运营成本高; 安全稳定性差、数据易丢失等问题亟待解决。 云主机的出现很大程度…

绘制一下包络线

clear clc close all % 生成衰减信号 % 生成衰减曲线带有随机信号 fs 50; % 采样率 t 0:1/fs:100; % 时间向量,总时长为5秒 frequency0.5; signal exp(-0.05* t).*sin(2*pi*frequency*t); % 衰减曲线带有随机信号 % 计算包络线 [upper_envelope, lower_…

6.5 共享数据

本节介绍Android的四大组件之一ContentProvider的基本概念和常见用法:首先说明如何使用内容提供器封装内部数据的外部访问接口,然后阐述如何使用内容解析器通过外部接口操作内部数据,最后叙述如何利用内容解析器读写联系人信息,以…