Go初识

Go

Go 初识

  • 编译型语言
  • 支持高并发

基本命令

  • go run 运行一个项目
  • go build 在不同的系统生成不同后缀的可执行文件,之后可以随时运行

Go代码格式

package main

import "fmt"

func main() {
    fmt.Println("Hello, world")
}
  • Go语言的代码通过包(package)组织,包类似于其它语言里的库(libraries)或者模块(modules)。

  • 每个源文件都以一条package声明语句开始

  • main包比较特殊。它定义了一个独立可执行的程序,而不是一个库

  • 在main里的main 函数也很特殊,它是整个程序执行时的入口,main函数所做的事情就是程序做的。

  • import 指定需要哪些包

  • import声明必须跟在文件的package声明之后

  • import 导入的包必须使用,如果不使用,不能通过编译

  • Go语言在代码格式上采取很强硬的态度,gofmt 工具可以把代码格式化为标准格式

  • goimports 工具可以根据代码需要,自动地添加或者删除import声明

  • 安装命令 go get golang.org/x/tools/cmd/goimports

格式化代码

  • gofmt filename.go
  • 参数 w 将格式化的内容覆盖原来的内容
  • 参数 r 后面加入用双引号括起来的替换规则实现代码的简单重构,规则的格式:<原始内容> -> <替换内容>

生成代码文档

  • go doc工具会从Go程序和包文件中提取顶级声明的首行注释以及每个对象的相关注释,并生成相关文档。
  • go doc package 获取包的文档注释,例如:go doc fmt 会显示使用 godoc 生成的 fmt 包的文档注释。
  • go doc package/subpackage 获取子包的文档注释,例如:go doc container/list。
  • go doc package function 获取某个函数在某个包中的文档注释,例如:go doc fmt Printf 会显示有关 fmt.Printf() 的使用说明。
  • 这个工具只能获取在 Go 安装目录下 …/go/src 中的注释内容。此外,它还可以作为一个本地文档浏览 web 服务器。在命令行输入 godoc -http=:6060,然后使用浏览器打开 http://localhost:6060 后,你就可以看到本地文档浏览服务器提供的页面。

Go语法

命名

  • 区分大小写
  • 一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线
  • 驼峰式命名
  • Go语言的风格是尽量使用短小的名字,对于局部变量尤其是这样

声明

  • Go语言主要有四种类型的声明语句:var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明。

  • 一个函数的声明由一个函数名字、参数列表(由函数的调用者提供参数变量的具体值)、一个可选的返回值列表和包含函数定义的函数体组成。

func fToC(f float64) float64 {
    return (f - 32) * 5 / 9
}


变量

变量一般声明语法
  • var 变量名字 类型 = 表达式
  • 其中“类型”或“= 表达式”两个部分可以省略其中的一个。如果省略的是类型信息,那么将根据初始化表达式来推导变量的类型信息。如果初始化表达式被省略,那么将用零值初始化该变量。
  • 数值类型变量对应的零值是0,布尔类型变量对应的零值是false,字符串类型对应的零值是空字符串,接口或引用类型(包括slice、指针、map、chan和函数)变量对应的零值是nil。
简短变量声明
  • 名字 := 表达式

  • 简短变量声明被广泛用于大部分的局部变量的声明和初始化。var形式的声明语句往往是用于需要显式指定变量类型地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方

  • 简短变量声明语句中必须至少要声明一个新的变量

指针
  • 一个变量对应一个保存了变量对应类型值的内存空间。
/*
如果用“var x int”声明语句声明一个x变量,那么&x表达式(取x变量的内存地址)将产生一个指向该整数变量的指针,指针对应的数据类型是*int,指针被称之为“指向int类型的指针”。如果指针名字为p,那么可以说“p指针指向变量x”,或者说“p指针保存了x变量的内存地址”。同时*p表达式对应p指针指向的变量的值。一般*p表达式读取指针指向的变量的值,这里为int类型的值,同时因为*p对应一个变量,所以该表达式也可以出现在赋值语句的左边,表示更新指针所指向的变量的值。
*/
x := 1
p := &x         // p, of type *int, points to x
fmt.Println(*p) // "1"
*p = 2          // equivalent to x = 2
fmt.Println(x)  // "2"
  • 任何类型的指针的零值都是nil。如果p指向某个有效变量,那么p != nil测试为真。指针之间也是可以进行相等测试的,只有当它们指向同一个变量或全部是nil时才相等。
package main 

import (
	"flag"
	"fmt"
	"strings"
)

var n = flag.Bool("n", false, "omit  trailing newline")
// 调用flag.Bool函数会创建一个新的对应布尔型标志参数的变量。它有三个属性:第一个是的命令行标志参数的名字“n”,然后是该标志参数的默认值(这里是false),最后是该标志参数对应的描述信息。
var sep = flag.String("s", " ", "separator")
//sep和n变量分别是指向对应命令行标志参数变量的指针
//因此必须用*sep和*n形式的指针语法间接引用它们

func main() {
	flag.Parse()
	fmt.Print(strings.Join(flag.Args(), *sep))
	if !*n {
		fmt.Println()
	}
}


new函数
  • 表达式new(T)将创建一个T类型的匿名变量,初始化为T类型的零值,然后返回变量地址
p := new(int)   // p, *int 类型, 指向匿名的 int 变量
fmt.Println(*p) // "0"
*p = 2          // 设置 int 匿名变量的值为 2
fmt.Println(*p) // "2"
  • 用new创建变量和普通变量声明语句方式创建变量没有什么区别,除了不需要声明一个临时变量的名字外,我们还可以在表达式中使用new(T)。
变量的生命周期
  • 变量的生命周期指的是在程序运行期间变量有效存在的时间间隔。

  • 对于在包一级声明的变量来说,它们的生命周期和整个程序的运行周期是一致的。而相比之下,局部变量的声明周期则是动态的:每次从创建一个新变量的声明语句开始,直到该变量不再被引用为止,然后变量的存储空间可能被回收

var global *int

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

  • 如果将指向短生命周期对象的指针保存到具有长生命周期的对象中,特别是保存到全局变量时,会阻止对短生命周期对象的垃圾回收(从而可能影响程序的性能)

类型

  • 一个类型声明语句创建了一个新的类型名称,和现有类型具有相同的底层结构。新命名的类型提供了一个方法,用来分隔不同概念的类型,这样即使它们底层类型相同也是不兼容的。

  • type 类型名字 底层类型

  • 通过这种类型转换可以用于区分不同类型的变量,如下面例子中,就不可以将Celsius和Fahreheit的数据放到一起来计算

package tempconv

import "fmt"

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) }


  • 命名类型还可以为该类型的值定义新的行为。这些行为表示为一组关联到该类型的函数集合,我们称为类型的方法集。
func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }

c := FToC(212.0)
fmt.Println(c.String()) // "100°C"
fmt.Printf("%v\n", c)   // "100°C"; no need to call String explicitly
fmt.Printf("%s\n", c)   // "100°C"
fmt.Println(c)          // "100°C"
fmt.Printf("%g\n", c)   // "100"; does not call String
fmt.Println(float64(c)) // "100"; does not call String
第一次写go遇到问题总结
  1. 导包
    • 问题 :invalid import path:
    • 原因 :包放的位置不对
    • 解决 :应该放在\$GOROOT或者 \$GOPATH 下的src目录下才可以
  2. 文件名
    • 问题 :no packages to build
    • 原因 :文件名的结尾是_test
    • 解决 :随便改个名就可以了。。
  3. 编码规范
    • 问题 :syntax error near unexpected token newline
    • 原因 : 左大括号 { 必须与方法的声明放在同一行,这是编译器的强制规定,否则你在使用 gofmt 时就会出现错误提示
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值