1. Go项目的目录结构

  一般的,一个Go项目在GOPATH下,会有如下三个目录:

  project

     --- bin

     --- pkg

     --- src

  其中,bin 存放编译后的可执行文件;pkg 存放编译后的包文件;src 存放项目源文件。一般,bin 和 pkg 目录可以不创建,go 命令会自动创建(如 go install),只需要创建 src 目录即可。对于 pkg 中的文件是 Go 编译生成的,而不是手动放进去的(一般文件后缀.a)对于 src 目录,存放源文件,Go 中源文件以包(package)的形式组织。通常,新建一个包就在src目录中新建一个文件夹。

注意:GOPATH 允许多个目录存在和配置,当有多个目录时,请注意分隔符,多个 GOPATH 的时候 windows 是分号,linux 和 mac 系统时冒号,当有多个 GOPATH 时,默认会将 go get 的内容放在第一个目录下。

  在最终形成项目后(可能还会依赖github上的一些包)整体结构图如下所示:

  

2. 行分隔符

  在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号( ; ) 结尾,因为这些工作都将由 Go 编译器自动完成。如果你打算将多个语句写在同一行,它们则必须使用分号( ; )人为区分,但在实际开发中我们并不鼓励这种做法。

3. 注释

  注释不会被编译,每一个包应该有相关注释。

  单行注释是最常见的注释形式,你可以在任何地方使用以 // 开头的单行注释。多行注释也叫块注释,均已以 /* 开头,并以 */ 结尾。如:

1
2
3
4
5
// 单行注释
/*
     Author by liangyongxing
     我是多行注释
 */

4. 内置关键字(25个都小写)

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

5. Go程序的顺序结构

  要想写出让人看着赏心悦目的代码,且具有一定的企业标准规范,一般都是需要有一定的规范才能达到指定的要求,下面就来说说这个规范到底是什么?

  1. 第一行一定是通过 package 来组织的,是通过关键词 import 来引入所依赖的包(与 python 相类似)  ps: import "fmt"

  2. 注意:只有 package 名称为 main 的包才可以包含 main 函数

  3. 在引入包之后紧接着是通过 const 关键字来进行常量的定义          ps: const PI = 3.14

  4. 在函数体外部通过使用 var 关键字来进行全局变量的声明和赋值        ps: var name = "liang"

  5. 通过 type 关键字进行结构struct 或 接口interface 的声明          ps: type Manager struct {}  或  type formatter interface {}

  6. 通过 func 关键字来进行函数的声明                     ps: func main() {}

按照以上顺序规范,编写的示例代码如下所示:

  1. // 当前程序的包名
  2. package main
  3.  
  4. /**
  5. 导入其他的包
  6. */
  7. import (
  8. std "fmt"
  9. )
  10.  
  11. // 常量定义
  12. const PI = 3.14
  13.  
  14. // 全局变量的声明和赋值
  15. var name = "liang"
  16.  
  17. // 一般类型声明
  18. type newType int
  19.  
  20. // 结构声明
  21. type Manager struct {
  22. }
  23.  
  24. // 接口声明
  25. type formatter interface {
  26. }
  27.  
  28. // 由 main 函数作为程序入口点启动
  29. func main() {
  30. std.Println("Hello World ! MyName is : " + name)
  31. }

 6. package 使用

1. 正常引用

1
import "fmt"

在此期间也可以使用别名,别名的主要作用就是当使用第三方包时,包名可能会非常接近或者相同,此时就可以使用别名来进行区别和调用,例如:

  1. import std "fmt"
  2. // 使用时可以通过别名直接调用
  3. std.Println("Hello World!")

2. 批量引入

  1. import (
  2. std "fmt"
  3. "io"
  4. str "strings"
  5. )

这里可以引伸一下,既然导入多个包时可以进行简写,那么声明多个 常量、全局变量 或 一般类型(非接口、非结构)是否也可以用同样的方式呢?

答案是肯定的,具体可见下面的案例:

  1. // 批量常量定义
  2. const (
  3. PI = 3.14
  4. CONSTA = "str"
  5. CONSTB = 1
  6. CONSTC = 2
  7. )
  8.  
  9. // 批量全局变量的声明
  10. var (
  11. name = "liang"
  12. name1 = "abc"
  13. name2 = 3
  14. )
  15.  
  16. // 批量一般类型声明
  17. type (
  18. newType int
  19. type_a float32
  20. type_b string
  21. type_c byte
  22. )

3. 省略调用

注意:

  1. 不建议使用,易混淆

  2. 不可以和别名同时使用

  1. import (
  2. . "fmt"
  3. )
  4.  
  5. func main() {
  6. // 使用省略调用
  7. Println("Hello World!")
  8. }

4. _ 操作

  这个操作经常是让很多人费解的一个操作符,请看下面这个import

  1. import(
  2. "database/sql"
  3. _ "github.com/ziutek/mymysql/godrv"
  4. )

  _  操作符其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的 init 函数

7. 可见性规则

  Go 语言中,使用 大小写 来决定该 常量、变量、类型、接口、接口 或 函数 是否可以被外部包所调用

  根据约定:

  1. 函数名 首字母 小写 即为 private

  2. 函数名 首字母 大写 即为 public

 8. Go基本类型

  1. 布尔型:bool

    -- 长度:1字节

    -- 取值范围:true/false

    -- 注意事项:不可以用数字代表 true 或 false

  2. 整型:int / uint

    -- 根据运行平台可能为 32 或 64 位

  3. 8位整型:int8 / uint8

    -- 长度:1字节

    -- 取值范围:-128~127 / 0~255

  4. 字节型:byte(是uint8别名)

    -- 长度:1字节

    -- 取值范围:0~255

  5. 16位整型:int16 / uint16

    -- 长度:2字节

    --取值范围:-32768~32767 / 0~65535

  6. 32位整型:int32(rune)/ unit32

    -- 长度:4字节

    -- 取值范围:-2^31~2^31-1 / 0~2^32-1

  7. 64位整型:int64 / uint64

    -- 长度:8字节

    -- 取值范围:-2^63~2^63-1 / 0~2^64-1

  8. 浮点型:float32 / float64

    -- 长度:4 / 8 字节

    -- 小数位:精确到 7/15 小数位

  9. 其他值类型

    -- array:数组类型

    -- struct:结构类型

    -- string:字符串类型

  10. 引用类型

    -- slice:切片类型

    -- map:哈希类型

    -- chan:管道类型

  11. 接口类型:interface

    函数类型:func

9. 变量的声明与赋值

 1. 单个变量的声明与赋值

  1. var a int // 变量的声明
  2. a = 123 // 变量的赋值
  3.  
  4. // 变量声明的同时赋值
  5. var b int = 321
  6.  
  7. // 上行的格式可以省略变量类型,有系统推断
  8. var c = 321
  9. // 变量声明与赋值的最简写法
  10. d := 456

 2. 多个变量的声明与赋值

  1. var a, b, c, d int // 多个变量的声明
  2. a, b, c, d = 1, 2, 3, 4 // 多个变量的赋值
  3.  
  4. // 多个变量声明的同时赋值
  5. var e, f, g, h int = 5, 6, 7, 8
  6.  
  7. // 省略变量类型,有系统推断
  8. var i, j, k, l = 9, 10, 11, 12
  9.  
  10. // 多个变量声明与赋值的最简写法
  11. i, m, n, o := 13, 14, 15, 16

  _ (下划线) 是个特殊的变量名,任何赋予它的值都会被丢弃。在下面的例子中,我们将值 35 赋予 b,并同时丢弃 34:

1
_, b := 34, 35

 3. 字符串

  Go中的字符串都是采用UTF-8字符集编码。字符串是用一对双引号("")或反引号(` `)括 起来定义,它的类型是string。在Go中字符串是不可变的,例如下面的代码编译是会报错:

1
2
var s string = "hello"
s[0] = 'c'

  但如果真对想要修改怎么办呢?下面的代码可以实现:

1
2
3
4
5
s := "hello"
c := []byte(s)    //将字符串 s 转换为 []byte 类型
c[0] = 'c'
s2 := string(c)   //再转换回 string 类型
fmt.Printf("%s\n", s2)

  Go 可以使用 + 操作符来连接两个字符串:

1
2
3
4
s := "hello"
m := " world"
a := s + m
fmt.Printf("%s\n", a)

  修改字符串也可以写为:

1
2
3
s := "hello"
s = "c" + s[1:]    //字符串虽然不能改,但可以进行切片操作
fmt.Printf("%s\n", s)

  如果想要声明一个多行的字符串怎么办呢?可以通过 `(反引号)来声明

1
2
m := `hello
      world`

  ` 括起的字符串为 Raw 字符串,即字符串在代码中的形式就是打印时代形式,它没有字符转义,换行也将原样输出。

 4. 错误类型

  Go 内置有一个 error 类型,专门用来处理错误信息,Go 的package里面专门还有一个 errors 来处理错误

1
2
3
4
err := errors.New("this is a error type, please check it.")
if err != nil {
    fmt.Printf("%s\n", err)
}

10. Go变量类型转换

  Go中不存在隐式转换,所有类型转换必须显式声明,且转换只能发生在两种相互兼容的类型之间

  1. // 在相互兼容的两种类型之间进行转换
  2. var a float32 = 1.1
  3. b := int(a)
  4.  
  5. // 以下表达式无法通过编译
  6. var c bool = true
  7. d := int(c)

  那么,请看以下代码,看最终结果应该是什么?

  1. func main() {
  2. var a int = 65
  3. b := string(a)
  4. fmt.Println(b)
  5. }

  运行结果位:A

  string() 表示将数据转换为文本格式,因为计算机中存储的任何内容本质上都是数字,因此此函数自然地认为我们需要的是数字65表示的文本为:A

  要想将数字转换为对应数字的字符串即:"65",则需要另外一个函数:strconv.Atoi(a) --> "65"

11. 常量的定义与应用

<1. 常量的定义

  1. 常量的值在编译时就已经确定

  2. 常量的定义格式与变量基本相同

  3. 等号右侧必须时常量或者常量表达式

  4. 常量表达式中的函数必须时内置函数

 示例如下:

  1. package main
  2.  
  3. import std "fmt"
  4.  
  5. // 定义单个常量
  6. const a int = 1
  7. const b = 'A'
  8.  
  9. // 批量定义多个常量
  10. const (
  11. text = "123"
  12. length = len(text)
  13. num = b * 20
  14. )
  15.  
  16. // 同时定义多个常量
  17. const i, j, k = 1, "liang", 'B'
  18.  
  19. func main() {
  20. std.Println(a, length, num, i, j, k)
  21. }

以上代码运行结果如下所示:

1
1 3 1300 1 liang 66

<2. 常量的初始化规则与枚举应用

  1. 在定义常量组时,如果不提供初始值,则表示将使用上行的表达式

  2. 使用相同的表达式不代表具有相同的值,例如下面介绍道道 iota

  3. iota 是常量的计数器,从 0 开始,组中每定义 1 个常量就会自动递增 1

  4. 通过初始化规则与 iota 可以达到枚举的效果

  5. 每遇到一个 const 关键字,iota 就会重置为 0

具体详情请看下面代码示例:

  1. package main
  2.  
  3. import std "fmt"
  4.  
  5. // 批量定义多个常量
  6. const (
  7. a = "A"
  8. b // a 与 b 都为 "A"
  9. c = iota
  10. d // d 的值为 c+1
  11. )
  12.  
  13. // 常量星期枚举应用
  14. const (
  15. // 第一个常量不可省略表达式
  16. _null = iota // 为了将 0 值排除
  17. Monday
  18. Tuesday
  19. Wednesday
  20. Thursday
  21. Friday
  22. Saturday
  23. Sunday
  24. )
  25.  
  26. func main() {
  27. std.Println(a, b, c, d)
  28. std.Println("星期列表:", Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
  29. }

以上代码运行结果如下所示:

1
2
A A 2 3
星期列表: 1 2 3 4 5 6 7

让我们再看一个结合常量的 iota 与 << (位运算符) 实现计算机存储单位的枚举示例:

  1. package main
  2.  
  3. import std "fmt"
  4.  
  5. const (
  6. _ = iota
  7. KB float64 = 1 << (iota * 10)
  8. MB
  9. GB
  10. TB
  11. PB
  12. EB
  13. ZB
  14. YB
  15. )
  16.  
  17. func main() {
  18. std.Println("KB:", KB)
  19. std.Println("MB:", MB)
  20. std.Println("GB:", GB)
  21. std.Println("TB:", TB)
  22. std.Println("PB:", PB)
  23. std.Println("EB:", EB)
  24. std.Println("ZB:", ZB)
  25. std.Println("YB:", YB)
  26. }

运行以上代码打印结果如下所示:

1
2
3
4
5
6
7
8
KB: 1024
MB: 1.048576e+06
GB: 1.073741824e+09
TB: 1.099511627776e+12
PB: 1.125899906842624e+15
EB: 1.152921504606847e+18
ZB: 1.1805916207174113e+21
YB: 1.2089258196146292e+24

12. 指针

  Go 虽然保留了指针,但与其他编程语言不同的是,在 Go 当中不支持指针运算以及 "->" 运算符,而直接采用 "." 选择符来操作指针目标对象的成员。

  1. 操作符 "&" 取变量地址,使用 "*" 通过指针间接访问目标对象

  2. 默认值为 nil 而非 NULL

  3. 在 Go 当中,++ 与 -- 是作为语句而并不是作为表达式的,这点很重要

以上三点通过以下例子来说明:

  1. package main
  2.  
  3. import (
  4. std "fmt"
  5. )
  6.  
  7. func main() {
  8. a := 1
  9. //a := a++ // 这里是编译不过去的,因为 ++ 与 -- 是作为语句而并不是作为表达式
  10. a++ // 语句需要单独一行
  11.  
  12. var p *int = &a
  13. std.Println(*p)
  14. }

运行结果打印如下:

1
2

申明:以上为Go语言最基础的一部分,下一节我会真对Go语言中的各种语句(if、for、switch等)进行说明。

GO语言基础语法的更多相关文章

  1. C语言基础语法

    #include <stdio.h> int main() { int age; printf("input your age"); scanf("%d&qu ...

  2. Smali语言基础语法

    1.Smali语言基础语法-数据类型与描述符 smali中有两类数据类型:基本类型和引用类型.引用类型是指数组和对象,其它都是基础类型. 基本类型以及每种类型的描述符: Java类型 类型描述符 说明 ...

  3. 黑马程序员——OC语言基础语法 面向对象的思想

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结)(一)基础语法 1)关键字 @interface.@implementati ...

  4. 黑马程序员——C语言基础语法 关键字 标识符 注释 数据及数据类型

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (一下内容是对黑马苹果入学视频的个人知识点总结) (一)C语言简单介绍 (1)C语言程序是由函数组成的任何C语言程序都是由一 ...

  5. php语言基础语法与编程工具推荐

    php脚本语言,需要在服务器端执行,用浏览器返回HTML结果.在PHP中所有的语法都是如此,用户端是无法修改的,只有浏览权限. 一.php基础语法之输出方法 1.PHP中所有的脚本,可以放在文件中的任 ...

  6. C语言基础语法之指向函数的指针

    指针是C语言的精髓,对于初学者来讲,指针是C语言语法学习中比较难的知识点,而这里面指向函数的指针更是不太容易理解. 下面给大家讲下怎样学习理解C语言中指向函数的指针及编程方法和使用例子. 注意:这是一 ...

  7. Python语言基础-语法特点、保留字与标识符、变量、基本数据类型、运算符、基本输入输出、Python2.X与Python3.X区别

    Python语言基础 1.Python语法特点 注释: 单行注释:# #注释单行注释分为两种情况,例:第一种#用于计算bim数值bim=weight/(height*height)第二种:bim=we ...

  8. NDK以及C语言基础语法(一)

    一.什么是NDK? Native Development Kit (本地开发工具包): NDK中提供了一系列的工具,帮助我们快速开发C/C++的动态库,并能自动将so文件和java文件一起打包成apk ...

  9. Go语言--基础语法笔记

    ### 换了工作,好久没有添加新文章了,本来是想更新到github上的,想想还是在博客里放着,感觉以前的文章都没有很仔细,都只是问题处理的记录, 以后想新加一些整理的笔记也好 ### 主要内容 2.1 ...

  10. GO_03:GO语言基础语法

    1. Go项目的目录结构 一般的,一个Go项目在GOPATH下,会有如下三个目录: project   --- bin   --- pkg   --- src 其中,bin 存放编译后的可执行文件:p ...

随机推荐

  1. 【基础知识】JavaScript基础

    [学习日记]JavaScript基础 1,一般写在<head></head>中(其实可以放到任意位置); 2,弹出对话框 <scripttype="text/j ...

  2. bs和cs

    CS(Client/Server):客户端----服务器结构.C/S结构在技术上很成熟,它的主要特点是交互性强.具有安全的存取模式.网络通信量低.响应速度快.利于处理大量数据.因为客户端要负责绝大多数 ...

  3. session过期情况下ajax请求不会触发重新登录的问题

    在拦截器中添加以下逻辑 String requestType = request.getHeader("X-Requested-With"); if (!StringUtils.i ...

  4. hihocoder 1509 异或排序

    题面在这里! 考虑前后两个数 x,y,可以发现S只有在(x xor y)的最高有1位上的取值是要被确定的 (如果x==y那么没有限制),可以推一下什么情况下是1/0. 于是我们模拟一下这个操作,判一判 ...

  5. uoj407 【IOI2018】狼人

    link 题意: 给一张n个点m条边的无向图,有q个询问,每次询问给出s,t,l,r,问你能否从s走到t,并且初始为人形,结束时必须为狼形,你是人形的时候必须避开$[1,l)$的节点,狼形的时候必须避 ...

  6. python 中__name__ = '__main__' 的作用,到底干嘛的?

    python 中__name__ = 'main' 的作用,到底干嘛的? 有句话经典的概括了这段代码的意义: "Make a script both importable and execu ...

  7. [COGS2479]偏序

    [COGS2479]偏序 题目大意: \(n(n\le50000)\)个四元组,求四维偏序. 思路: CDQ分治套CDQ分治套树状数组. 细节: 第二层CDQ之前要备份数组\(a\),否则第二层CDQ ...

  8. 【10.29校内测试】【线段树】【DP】【二进制Trie树求最小值最大】

    Solution 标程太暴力惹QAQ 相当于是26棵线段树的说QAQ 不过我写了另一种写法,从大到小枚举每一个字母,标记字典序在这个字母之上的位置为1,每次都建一棵线段树,维护1的数量,即区间和. 修 ...

  9. HDOJ 4414 Finding crosses 暴力!

    Finding crosses Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  10. Java Threads 多线程10分钟参考手册

    1         同步 如何同步多个线程对共享资源的访问是多线程编程中最基本的问题之一.当多个线程并发访问共享数据时会出现数据处于计算中间状态或者不一致的问题,从而影响到程序的正确运行.我们通常把这 ...