• 认真地记录技术中遇到的坑!

Go语言环境搭建和基本语法

Go 悠悠 3个月前 (02-13) 270次浏览 0个评论

GO语言学习笔记

环境准备

Windows安装GO语言环境安装

安装包下载地址:https://golang.org/dl/,推荐选择Windows版本的msi格式安装包,简单些。
32位的电脑选择:go1.11.5.windows-386.msi
64位电脑选择:go1.11.5.windows-amd64.msi (111M)

GO语言中国社区:https://studygolang.com/dl

IDE我是使用jetbrain的GoLand,下载地址:https://www.jetbrains.com/go/whatsnew/ (220M),激活码生成方法:http://idea.lanyus.com/

优点是自动补全很好用,功能强大,但是很重。
比较轻量级的可以考虑VSCode,有相应的GO插件可以用

大概100M左右,下载完之后,双击安装即可,安装过程中可以选一个比较好的安装目录。

GO语言IDE选择

IDE我是使用jetbrain的GoLand,下载地址:https://www.jetbrains.com/go/whatsnew/ (220M),激活码生成方法:http://idea.lanyus.com/

GoLang的优点是自动补全很好用,功能强大,但是很重。

比较轻量级的可以考虑VSCode,有相应的GO插件可以用。

另外需要配置一下GoLang,进入GoLang,打开一个文件夹,比如Go_Projects。

  • 修改主题颜色为黑色的方法:File -> Setting -> Appearance & Behavior -> Theme -> 默认是Intellij,黑色是Darcula
  • 修改字体大小方法:File -> Setting -> Editor -> Font,在右边选项框中选择字体即可,推荐Console,18号
  • 配置Go语言执行环境方法:File -> Setting -> Go -> GOROOT -> 选择GO语言的安装目录即可。
  • 配置Go语言GOPATH:File -> Setting -> Go -> GOPATH -> 选择当前项目所在的路径即可。

测试环境:在GoLang LED中新建一个文件:hello.go,加入下面内容:

package main

import "fmt"

func main() {
    /* 这是我的第一个简单的程序 */
    fmt.Println("Hello, World!")
}

右键运行,如果在控制台打印出 hello,world!说明IDE和Go执行环境都已经准备完毕。

另外如果将Go的安装目录下的bin添加到系统环境变量(msi安装文件默认添加),可以执行下面命令运行go语言文件:

go run helll.go

基本语法

该部分介绍Go语言的一些基础用法,适用于有一定编程语言的同学。

Go程序结构

根据上面的hello.go文件,我们可以看出,一个Go语言执行文件包含下面几个部分:

  • package main:指定当前文件所属的包名,package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。
  • import "fmt": 表示导入fmt的包,导入包后可以使用该包中的函数,fmt 包实现了格式化 IO(输入/输出)的函数
  • func main():声明main()函数,表示该文件的执行入口,main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)

Go语言基础语法规则

  • 语句分割:一行代表一个语句结束,不需要额外的分号,如果一行包含多个语句,则必须使用分号隔开,这种方式不推荐
  • 注释:使用//进行单行注释,使用/* */进行多行注释
  • 标识符:字母(A~Z和a~z)数字(0~9)、下划线_组成,第一个字符必须是字母或下划线而不能是数字。
  • 空格:空格不影响语句解析,变量声明必须使用空格隔开
fmt.Println("Hello") // 单行单条语句不需要分号
fmt.Println("Hello");fmt.Println(" world")  // 单行多条语句需要分号分割

// 单行注释
/*
 多行注释
 多行注释
 */

// 定义变量
var age int

Go语言变量使用

Go语言变量定义语法:var identifier type,定义方式包含三种:

  • 指定变量类型,声明后若不赋值,使用默认值
  • 根据值自行判定变量类型
  • 省略var,使用 := 定义函数内变量

需注意:函数内变量定义后未使用会报编译错误,全局变量则不会报错

// 指定变量类型,声明后若不赋值,使用默认值。
var v_name v_type
v_name = value

// 根据值自行判定变量类型。
var v_name = value

// 省略var,使用 := ,此时变量不应该是已经声明过的,否则会导致编译错误
v_name := value

Go语言支持变量结构,即多个变量声明:

package main

var x, y int
var (
    a int
    b bool
) // 这种因式分解关键字的写法一般用于声明全局变量

var c, d int = 1, 2
var e, f = 123, "hello"
e += 12  // 使用变量

//这种不带声明格式的只能在函数体中出现
// g, h := 123, "hello"

func main() {
    // 使用 := 定义函数内变量
    // 如果定义var 1 int = 4, 不使用的话会报编译错误
    g, h := 123, "hello"
    println(x, y, a, b, c, d, e, f, g, h)
}

另外说明一下Go语言中变量的作用域,Go语言中变量的作用域为函数级。

  • 函数内定义的变量称为局部变量:函数内作用域
  • 函数外定义的变量称为全局变量:全局作用域
  • 函数定义中的变量称为形式参数:函数内作用域

如果定义的变量没有初始化,则使用默认值

  • int类型的初始值为:0
  • float32类型的初始值为:0
  • string类型的初始值为:””
  • pointer类型的初始值为:nil

Go语言常量使用

Go语言常量定义的语法:const identifier [type] = value,一般常量所有字母大写,定义方式如下:

  • 显式类型定义:const b string = “abc”
  • 隐式类型定义:const b = “abc”
  • 多个常量定义:const c_name1, c_name2 = value1, value2
  • 枚举定义方式:const ( Unknown = 0; Female = 1; Male = 2)

常量定义时可以使用函数,函数值应该是编译是能够确认的值。

package main

import "unsafe"
const (
    a = "abc"
    b = len(a)
    c = unsafe.Sizeof(a)
)

func main(){
    println(a, b, c)
}

这里不得不说一个特殊常量iota,这个常量由编译器来进行管理。

iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

// 第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1
const (
    a = iota   // 0
    b          // 1
    c          // 2
    d = "ha"   // 独立值,iota += 1
    e          // "ha"   iota += 1
    f = 100    // iota +=1
    g          // 100  iota +=1
    h = iota   // 7,恢复计数
    i          // 8
)
fmt.Println(a,b,c,d,e,f,g,h,i)  // 常量可以直接使用

Go语言运算符

Go语言的运算符和PHP等语言类似,包括:

  • 算术运算符: +、-、*、/、%、++、–
  • 关系运算符: ==、!=、>、<、>=、<=
  • 逻辑运算符: &&、||、!
  • 位运算符: &、|、^、<<、>>
  • 赋值运算符: =、+=、-=、*=、/=、%=、<<=、>>=、&=、^=、!=
  • 指针运算符: &(返回变量存储地址)、*(指针变量)

Go语言中有指针的概念,这里特别说明两个指针操作运算符

var a int = 4
var ptr *int

ptr = &a  // 取a变量的地址并复制给指针ptr
*ptr = 20 // 修改ptr指针地址所指向的内存空间,相当于修改a=20,此时a=20

Go语言流程控制: if else

Go语言中的流程控制条件不需要括号,条件语句语法:

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
}

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
} else {
  /* 在布尔表达式为 false 时执行 */
}

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
} else if 布尔表达式 {
  /* 在布尔表达式为 false 时执行 */
} else {
  /* 在布尔表达式为 false 时执行 */
}

if 布尔表达式 1 {
   /* 在布尔表达式 1 为 true 时执行 */
   if 布尔表达式 2 {
      /* 在布尔表达式 2 为 true 时执行 */
   }
}

条件语句实例如下:

package main

import "fmt"

func main() {
    var age int = 23
    if age == 25 {
        fmt.Println("true")
    } else if age < 25 {
        if age == 0 {
            fmt.Println("zero")
        } else {
            fmt.Println("too small")
        }
    } else {
        fmt.Println("too big")
    }
}

Go语言流程控制: switch

switch语法中,区别于其他如PHP等语言,需注意以下几点

  • 默认每个case后面的case不执行,除非使用fallthrough关键字强制执行后面的 case 语句
  • 使用fallthrough关键字执行下一条匹配的case
  • 使用case val1, val2, val3的方式多个case执行相同代码
package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var grade string = "B"
   var marks int = 90
   var x interface{}

   switch marks {
      case 90: grade = "A"
      case 80: grade = "B"
      case 50,60,70 : grade = "C"
      default: grade = "D"  
   }

   // 可以省略switch后面的判断变量
   switch {
       case marks == 90 : grade = "A"
       case marks == 80 : grade = "B"; fallthrough  // 强制执行下一个case,即当marks=80时,grade="C"
       case 50,60,70 : grade = "C"
       default: grade = "D"
   }

   // 另外switch可以用来进行类型处理
   var x_type = ""
   switch i := x.(type) {
       case nil: x_type = "nil"
       case int: x_type = "int"
       case float64: x_type = "float64"
       case func(int) float64: x_type = "func(int) float64"
       case bool, string: x_type = "bool or string"
       default: x_type = "unknown"
    }
}

另外Go语言中还有特有的类似于用于通信的switch语句,select语法,此次不做介绍。

Go语言流程控制: for

Go语言中循环语句值包括for,另外还有breakcontinuegoto循环控制。

Go语言中for循环有三种形式:

  • 带初始条件:for init; condition; post { }
  • 只有循环终止条件:for condition { }
  • 永久循环:for { }

其中:

  • init: 一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量。

下面是一个示例:

package main

import "fmt"

func main() {

   var b int = 15
   var a int

   numbers := [6]int{1, 2, 3, 5} 

   /* for 循环 */
   for a := 0; a < 10; a++ {
      fmt.Printf("a 的值为: %d\n", a)
   }

   for a < b {
      a++
      fmt.Printf("a 的值为: %d\n", a)
   }

   for i,x:= range numbers {
      fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
   }   
}

Go语言数据类型

概述

在 Go 编程语言中,数据类型用于声明函数和变量,Go语言是一门强类型语言。Go语言的数据类型可分为以下几个大类。

类型 描述
布尔型 常量 true 或者 false
数字类型 整型,浮点型,Go语言支持复数,采用补码运算
字符串类型 单个字节连接,使用 UTF-8 编码标识 Unicode 文本,字符串只能使用双引号表示
派生类型 包括指针类型,数组类型等

数字类型

数字类型包括整数和浮点数,如下:

类型标识 描述
int 32或64位整型(根据平台觉得是32位还是64位)
uint 和int一样
uintptr 无符号整型,用于存放一个指针
byte 8个字节
rune 32个字节
uint8 无符号8位整型
uint16 无符号16位整型
uint32 无符号32位整型
uint64 无符号64位整型
int8 有符号8位整型
int16 有符号16位整型
int32 有符号32位整型
int64 有符号64位整型
float32 EEE-754 32位浮点型数
float64 IEEE-754 64位浮点型数
complex64 32位实数和虚数
complex128 64位实数和虚数

派生类型

派生类型包括下面几种:

  • 指针类型
  • 数组类型
  • 结构化类型
  • Channel类型
  • 函数类型
  • 切片类型
  • 接口类型
  • Map类型

Go语言类型转换

Go语言类型转换很简单:type_name(expression)

比如将float32转换为int:var f int = int(10.65)

值类型和引用类型

所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值。

当使用等号 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝

可以通过 &i 来获取变量 i 的内存地址,一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个字所在的位置。

当使用赋值语句 r2 = r1 时,只有引用(地址)被复制(浅拷贝),如果 r1 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,r2 也会受到影响。

Go语言函数

Go语言函数定义

每个Go语言文件最少有个 main() 函数。Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
   函数体
}
  • func:函数由 func 开始声明
  • function_name:函数名称
  • parameter list:参数列表,可选,Go语言中默认使用值传递参数
  • return_types:返回类型,没有return时可以不用写该项
  • 函数体:函数定义的代码集合

实例如下

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

函数调用

传入参数即可调用函数。

package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int = 200
   var ret int

   /* 调用函数并返回最大值 */
   ret = max(a, b)

   fmt.Printf( "最大值是 : %d\n", ret )
}

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 定义局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

函数可返回多个值

package main

import "fmt"

func swap(x, y string) (string, string) {
   return y, x
}

func main() {
   a, b := swap("Mahesh", "Kumar")
   fmt.Println(a, b)
}

函数的附加说明

Go语言中的函数功能非常强大,包括以下几点:

  • 可以使用函数作为参数传递,用于回调函数等场景
  • 可以返回匿名函数,用作函数闭包
  • 可以和对象绑定,用作方法

Go语言指针

和C语言一样,Go语言还支持指针。一个指针变量指向了一个值的内存地址。

Go语言指针声明

指针的声明很简单,只需要在你声明的类型前面加上*即可:var var_name *var-type

// 声明一个整数类型的指针:该地址指向一个整型
var ip *int

// 声明一个整数类型的指针:该地址指向一个浮点型
var fp *float32

如果只是声明指针没有赋值,则指针的值为空指针nil

Go语言指针使用

指针的操作主要有取地址操作符:&和取值操作符:.

package main

import "fmt"

func main() {
    var num int = 20   // 声明实际变量
    var numPtr *int        // 声明指针变量
    numPtr = &num  // 指针变量的存储地址
    fmt.Println("num: ", num)  // 20
    fmt.Println("numPtr: ", numPtr) // 内存地址:0xc00000a0e0
    *numPtr = 1  // 修改指针指向的内存区域的值,相当于修改 num=1
    fmt.Println("numPtr: ", *numPtr) // 1
}

喜欢 (1)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址