Go基础学习二之常用命令、包、变量、常量、控制语句、range

Go编程语言:支持并发、垃圾回收的编译型系统级编程语言!本文主要是按照无闻的《Go 编程基础》开源视频学习并记录笔记。

一、go语言常用命令

go get 获取远程包(需提前安装git)
go run 运行
go build 测试编译(package main 的文件)
go fmt 格式化代码
go install 编译包文件和整个程序
go test 运行测试文件(**_test.go是测试文件,命名自己文件的时候需要注意)
go doc 查看文档(本地官网 godoc -http=:8080 & 后台执行)

我们可以将go的官网放到本地:

godoc -http=:8080

然后我们可以访问本地8080端口:

http://localhost:8080/

Go环境变量与工作目录:GOPATH下需要建立 3个目录(bin存放编译后生成的可执行文件;pkg存放编译后生成的包文件;src存放项目源码)

二、go 语法结构

1、Go导入package的格式

package main包含main函数
一个程序有且只有一个main包和一个main函数
package 要放在非注释的第一行
package 后加import,import 引入非main包
一般建议package的名称和目录名一致 pacage 名称不要使用驼峰标记法,使用下划线
var 全局变量
type 基本类型 比如:type newtype struct/interface{(内容)}

改包名:

import abc "fmt"/import . "fmt"

调用的时候

abc.Println/Println

不推荐使用.那种,容易混淆

只有packagemain 的包可以包含main函数,一个可执行程

test.go


package ok
// package main  这里故意将main 包名写错

import "fmt"

func main(){
    fmt.Println("Hello, World")
}

如果我们运行的程序里边没有 package main 包,则执行会报错;
➜ src go run myfirstgo/test.go go run: cannot run non-main package

  • 导入包之后,就可以使用格式<PackageName>.<FuncName>
  • 如果导入包之后 未调用 其中的函数类型将会报出编译错误

import and not used:"io";

2、package别名

当使用第三方包时,包名可能会非常接近或相同,此时就可以使用别名来进行区别和调用

import "fmt"

// 使用别名
import std "fmt"
std.Println("Hello,world")

省略调用

// 省略调用
import . "fmt"
Println("Hello,world")

注意点:
1.不建议使用省略调用,易混淆
2.不可以和别名同时使用

3.可见性规则

Go语言中,使用 大小写 来决定该常亮、变量、类型、接口、结构或函数,是否可以被外部包所调用:
根据约定,函数名首字母小写即为private

func getField(){
  // ...
}

函数名首字母大写即为public

func Print(){
  // ...
}

完整示例:

package main

// 导入其他的包
import "fmt"     // 第一种导入方法
/*
import{
    "fmt"
    "io"
    "os"
}
*/

// 常量的定义
const PI = 3.14

// 全局变量的声明与赋值
var name = "gopher"

// 一般类型声明
type newType int

// 结构的声明
type gopher struct{}

// 接口的声明
type golang interface{}

// 由 main 函数作为程序入口点启动
func main(){
    fmt.Println("Hello, World")
}

牛刀小试:
既然导入多个包可以进行简写,那么声明多个常亮、全局变量或一般类型(非接口、非结构)是否也可以使用同样的方法呢?

定义常亮:

const(
  PI = 3.14
  const1 = 1
  Radis = 10
)

全局变量的声明与赋值:

var (
 name = "corwien"
 age  = 20
 address = "guangzhou"
)

一般类型声明:

type (
 newType int
 type1 float32
)

三、类型与变量

1.类型

1、布尔类型:bool
长度:1字节
取值范围:true,false
注意事项:不可以用数字代表true或false

2、整型:int/uint
-根据运行平台可能为32或64位

3、8位整型:int8/uint8
-长度:1字节
-取值范围:-128~127/0~255

4、字节型:byte(uint8别名

5、16位整型:int16/uint16
-长度:2字节
-取值范围:-32768~32767/0~65565

6、32位整型:int32(rune)/uint32
-长度:4字节
-取值范围:-32768~32767/0~65565

7、浮点型:float32/float64
-长度:4/8字节
-小数位:精确到7/15小数位

8、复数:complex64/complex128
-长度:8/16字节
足够保存指针的32、64位整数型:uintptr

9、其他值类型:

  • array、struct、string

10、引用类型:

  • slice,map,chan

11、接口类型:interface
12、函数类型:func,可以赋值给变量

类型零值

零值并不等于空值,而是当变量被声明为某种类型后的默认值,通常情况下值类型的默认值为0,bool为false, string为空字符串

类型别名

type (
  byte int8
  rune int32
  文本 string
)

// 使用中文类型,牛逼啊
var b 文本
b = "你好哈亲"

2.变量

2.1 单个变量的声明与赋值

  • 变量的声明格式:var <变量名称><变量类型>
  • 变量的赋值格式:<变量名称> = <表达式>
  • 声明的同时赋值:var <变量名称>[变量类型] = <表达式>

示例:

var a int // 变量的声明
a = 123   // 变量的赋值

// 变量声明的同时赋值
var a int = 123

// 上行的格式可省略变量类型,由系统推断
var c = 123

// 变量声明与赋值的最简写法
d := 678

d := 678 冒号的作用就是代替关键字 var 的

2.2 多个变量的声明与赋值

  • 全局变量的声明可以使用var()的方式进行简写
  • 全局变量的声明不可以省略var,但可以使用并行方式
  • 所有变量都可以使用类型推断
  • 局部变量不可以使用var()的简写,只能使用并行方式

举例:

var(
  // 使用常规方式
  a = 'hello'
 
  // 使用并行方式以及类型推断
   b,c = 1,2
  // d := 3 // 不可以省略 var
)

多个变量的声明

// 多个变量的声明
var a, b, c int

// 多个变量的赋值
a, b, c = 1, 2, 3

// 多个变量声明的同时赋值
var d, e, f int = 4, 5, 6

// 省略变量类型,有系统推断
var g, h, m  = 7, 8, 9

// 多个变量声明与赋值的最简写法
n, o, p := 10, 11, 12

2.3 变量的类型转换

  • Go中不存在隐式转换,所有类型转换必须显示声明
  • 转换只能发生在两种相互兼容的类型之间
  • 类型转换的格式:
// 当变量未在前边申明过,则需要冒号:,如果已经声明过,则不需要冒号
<ValueA>[:] = <TypeOfValueA>(<ValueB>)

示例:

// 在相互兼容的两种类型之间转换
var a float32 = 1.1
b := int(a)

// 以下表达式无法通过编译
var c bool = true
d := int(c)
全局变量的声明不可以省略var 局部变量不可以使用var()的方式简写

思考
尝试运行下边的代码,开会发生什么,并思考为什么?

// 变量类型转换,整数转为字符,会发生什么呢?
func main() {
    var a int = 65
    b := string(a)
    fmt.Println(b)
}

四、常量与运算符

1、常量的定义

  • 常量的值在编译时就已经确定
  • 常量的定义格式与变量基本相同
  • 等号右侧必须是常量或者常量表达式
// 定义单个常量
const a int = 1
const b = 'A'
const {
  text = "123"
  length = len(text)
  num = b * 20
}

// 同时定义多个变量
const i, j, k = 1, "2", "3"
const(
  text2, length2, num2 = "234", len(text2), k * 10
)

2、常量的初始化规则与枚举

  • 在定义常量组时,如果不提供初始值,则表示将使用上行的表达式
  • 使用相同的表达式不代表具有相同的值
  • iota是常量的计数器,从0开始,组中每定义1个常量自动递增1
  • 通过初始化规则与iota可以达到枚举的效果
  • 每遇到一个 const 关键字,iota就会重置为0

示例:

const (
    // a与b都为"A"
    a = "A"
    b
    c = iota
    d // d的值为3
)

const(
  e = iota
  f // f 的值为1
)

// 星期枚举
const(
  // 第一个常量不可省略表达式
    Monday = iota
    Tuesday
    Wednesday
    Thursday
    Firday
    Saturday
    Sunday
)

3、运算符

  • Go中的运算符均是从左至右结合
    优先级(从高到底)
  • ^ ! (一元运算符)
  • * / % << >> & &^
  • + – | ^ (二元运算符)
  • == != < <= >= >
  • <- (专门用于channel)
  • &&
  • ||

4、指针

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

  • 操作符“&”取变量地址,使用“*”通过指针间接访问目标对象
  • 默认值为 nil 而非NULL
func main() {
    a := 1
    var p *int = &a;

    // fmt.Println(p)   打印地址:0xc42000e228
    fmt.Println(*p)    // 打印结果: 1
    
}

5、递增递减语句

在Go当中, ++ 与 — 是作为语句而并不是作为表达式

五、控制语句

1、判断语句if

  • 条件表达式没有括号,这和其他语言不太一样
  • 支持一个初始化表达式(可以是并行方式)
  • 左大括号必须和条件语句或else在同一行
  • 支持单行模式
  • 初始化语句中的变量为block级别,同时隐藏外部同名变量
  • 1.0.3版本中的编译器Bug

示例:

package main


import "fmt"  


func main() {

    a := true

    // 初始化变量,在块里边初始化,作用域只是在该区块中
    if a, b, c := 1, 2, 3; a+b+c > 6 {
        fmt.Println("大于6")  
        fmt.Println(a)

    } else {
        fmt.Println("小于等于6")
        fmt.Println(a)

    }

    fmt.Println(a)  
    
}

打印结果:

➜  myfirstgo go run if.go
小于等于6
1
true

2、循环语句for

  • Go 只有 for 一个循环语句关键字,但支持3种形式
  • 初始化和步进表达式可以是多个值
  • 条件语句每次循环都会被重新检查,因此不建议在条件语句中使用函数,尽量提前计算好条件并以变量或常量代替
  • 左大括号必须和条件语句在同一行

for 循环的三种形式:
1.最简单的

func main() {
    
    a := 1
    for {
        a++
        if a > 3 {
            break
        }
    }
    fmt.Println(a)
}

2、条件语句判断

func main() {
    
    a := 1
    for a <= 3 {
        a++
    }
    fmt.Println(a)
}

3、最常用的一种方式

func main() {
    
    a := 1
    for i := 0; i < 3; i++ {
        a++
    }
    fmt.Println(a)
}

3、选择语句switch

  • 可以使用任何类型表达式作为条件语句
  • 不需要写break,一旦条件符合自动终止
  • 如希望继续执行下一个case,需使用fallthrough语句
  • 支持一个初始化表达式(可以是并行方式),右侧需跟分号
  • 左大括号必须和条件语句在同一行

示例:

// switch

func main() {
    a := 1
    switch a {
    case 0:
        fmt.Println("a=0")
    case 1:
        fmt.Println("a=1")
    default:
        fmt.Println("Nothing")
    }
    fmt.Println(a)
}
func main() {
    a := 1
    switch {
    case a >= 0:
        fmt.Println("a=0")
        fallthrough
    case a >= 1:
        fmt.Println("a=1")
    }
    fmt.Println(a)
}
func main() {
    
    switch a := 1; {
    case a >= 0:
        fmt.Println("a=0")
        fallthrough
    case a >= 1:
        fmt.Println("a=1")
    }
    
}

4、跳转语句goto,break,continue

  • 三个语法都可以配合标签使用
  • 标签名区分大小写,若不使用会造成编译错误
  • Break与continue配合标签可用于多层循环的跳出
  • Goto 是调整执行位置,与其他2个语句配合标签的结果并不相同

示例:

func main() {
// 标签
LABLE:
  for {
      for i := 0; i < 10; i++ {
          if i > 3 {
              break LABLE
          }

      }
  }
    
    fmt.Println("ok")
}
func main() {
LABLE:
      for i := 0; i < 10; i++ {
          for {
              continue LABLE
              fmt.Println(i)
          }
  }
    
    fmt.Println("ok")
}

六、语言范围 Range

Go 语言中 range 关键字用于for循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引值,在集合中返回 key-value 对的 key 值。

示例:

package main
import "fmt"
func main() {
    //这是我们使用range去求一个slice的和。使用数组跟这个很类似
    nums := []int{2, 3, 4}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:", sum)
    //在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
    for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
    }
    //range也可以用在map的键值对上。
    kvs := map[string]string{"a": "apple", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }
    //range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}

运行结果:

sum: 9
index: 1
a -> apple
b -> banana
0 103
1 111

相关资源:
Go 编程基础
Go学习笔记整理

    原文作者:Corwien
    原文地址: https://segmentfault.com/a/1190000011330662
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞