golang学习随便记1

Posted sjg20010414

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang学习随便记1相关的知识,希望对你有一定的参考价值。

准备工作

用vscode编写golang程序显然要麻烦一点,另外,在墙内也是多了一些麻烦,好在资源够多:

go get更换国内镜像源_goldVitaminC的博客-CSDN博客   用镜像才能顺利下载包(包括vscode插件)

The Go Programming Language (google.cn)   这个代替官网

以前是在linux下用,而且是先 gcc 编译低版本go,然后再用低版本go编译高版本编译器,windows下就直接下载二进制安装包 .msi 了,装完:

C:\\Program Files\\Go    这里是 go 自己的东西,包括标准库包,

用户主目录 %HOMEPATH% (如 c:\\users\\zime)下有go子目录,里面有 bin、src 和 pkg 子目录,当我们使用其他包(包括插件)时,下载到 pkg 子目录。我们的源代码放入src子目录(每个项目里面建立一个子目录)

和我以前用 go 不一样的地方是,现在推荐项目下有名称为 go.mod 的依赖跟踪文件,如果原来没有也简单  go  mod  init  模块路径名,这里 模块路径名  通常是项目在仓库的路径,类似 github.com/mymodule,这样可以确保 go的那些工具能下载这个包(如果我们的包并不需要给他人用,可以随便给个名称)

命令行参数

引入 "os" 包,os.Args 数组存放了命令行参数,项目 echo1

package main

import (
	"fmt"
	"os"
)

func main() {
	var s, sep string
	for i := 1; i < len(os.Args); i++ {
		s += sep + os.Args[i]
		sep = " "
	}
	fmt.Println(s)
}

os.Args[0] 为命令自己,os.Args[1]为第一个参数 ,如 go build 编译,./echo1  aaa  bbb  ccc 将输出 aaa  bbb  ccc

程序结构

常量

const boilingF = 212.0
const freezingF, boilingF = 32.0, 212.0

变量

var s string
var i, j, k int
var b, f, s = true, 2.3, "four"
var f, err = os.Open(name)

短变量声明,即用  :=  在赋值的同时声明变量,用所赋值确定变量的类型,如

anim := gif.GIF { LoopCount: nframes }
freq := rand.Float64() * 3.0
t := 0.0
i, j := 0, 1
f, err := os.Open(name)

指针

和C指针基本类似,这里先略过

new函数

p := new(int)
fmt.Println(*p)  // 0
*p = 2
fmt.Println(*p)  // 2

new()是内置函数,不是关键字(可以有变量名为new,但它的作用下不能调用new()函数),相当于分配内存返回指针,因为 go中变量总是初始化的,所以上例中第一条打印语句输出0

变量生命周期

var global *int

func f() {
  var x int
  x = 1
  global = &x
}

上例中,存在“变量逃逸”现象,即变量 x 尽管在函数 f 内部局部声明,但其地址赋值给了全局变量global,所以,编译器必然会将其分配在堆上。go可以保证变量逃逸下程序仍能正常运行,但过多的变量逃逸可能带来性能问题。

命名类型(类型别名)

这个差不多就是 typedef 的意思,例如定义两个类型分别表示摄氏温度类型和华氏温度类型:

type Celsius float64
type Fahrenheit float64

命名了这两个新类型之后,就可以用来声明常量和变量了

const (
  AbsoluteZeroC Celsius = -273.15
  FreezingC  Celsius = 0
  BoilingC  Celsius = 100
)

func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }

值得注意的是,golang是比C++ “更强”的强类型语言,上面的例子中,尽管 Celsius 和 Fahrenheit 内部都是 64位浮点数,但不能直接把一个 Celsius 类型的变量值赋值给 Fahrenheit 类型的变量(反之亦然),也不能用一个Celsius类型变量减去(或加上)另一个Fahrenheit类型的变量,必须进行显式类型转换,上例中 Celsius(t) 和 Fahrenheit(t) 是类型转换,不是函数。

我们可以为新命名的类型“附加”它的字符串表达,即为类型附加 String() 方法,从而打印该变量时,会按指定的字符串表达输出——这个和php里面 echo $v; 时,输出$v的字符串表达一样(如果$v 是类实例,则 $v 的魔术方法 __toString() 自动被调用)

func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }

大致按以下意思理解:func + 拥有者实例c + String() + 返回类型 { ... return ... }

如果 

c := FToC(212.0)

则直接 fmt.Println(c) 将输出 100°C,当然,我们仍然可以输出 c 的值

fmt.Println(c.String())  // "100°C"
fmt.Printf("%v\\n", c)    // "100°C"
fmt.Printf("%s\\n", c)    // "100°C"
fmt.Println(c)           // "100°C"
fmt.Printf("%g\\n", c)     // "100"
fmt.Printfln("float64(c)) // "100"

包和文件

golang每个文件开头都用 package 声明定义包的名称,当我们导入一个其他包时,那个包的成员(导出常量、导出变量、导出函数)可以用 packagename.CToF那样的方式引用。注意:这里有一个被王垠大神吐槽的点,就是哪些标识符是被导出的,哪些是外部不可见的,是按首字符大小写约定的(大写字母开头导出的,外部可见,小写字母开头是包内私有的)

包使用例子,创建 greetings 目录 和 hello目录,我们将在 hello项目引用greetings包。

<ch1>/
 |-- greetings/
 |-- hello/

在greetings目录用 go mod init example.com/greetings 创建依赖文件,然后创建 greetings.go 源文件如下:

package greetings

import "fmt"

func Hello(name string) string {
	message := fmt.Sprintf("Hi, %v. Welcome!", name)
	return message
}

注意,函数Hello首字母是大写的!

在 hello 目录同样用 go mod init example.com/hello 创建依赖文件,然后创建源代码文件 hello.go

package greetings

import "fmt"

func Hello(name string) string {
	message := fmt.Sprintf("Hi, %v. Welcome!", name)
	return message
}

这样直接 go run . 会出错,因为 go get 试图从仓库中去找 greetings 包,我们必须在 hello 项目的依赖文件告诉编译器,从本地文件系统找该包,所以,执行

go mod edit -replace example.com/greetings=../greetings

这时, go.mod 文件就多一句 replace 语句,再用 go mod tidy 同步一下模块依赖(就是找出我们的源码依赖哪些外部包,它们的版本是什么,然后在 go.mod 依赖文件进行记录),hello的go.mod文件如下

module example.com/hello

go 1.17

replace example.com/greetings => ../greetings

require example.com/greetings v0.0.0-00010101000000-000000000000

这时 go run . 就可以正常工作了

作用域

基本上和直觉一致,略过

以上是关于golang学习随便记1的主要内容,如果未能解决你的问题,请参考以下文章

golang学习随便记14

golang学习随便记14

golang学习随便记9

golang学习随便记3

golang学习随便记12

golang学习随便记7