Go 学习笔记1 - 基础知识 |Go主题月

257 阅读5分钟

一、基础知识

1.Go内置关键字和注释方法

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

2.Go程序的一般结构

//当前程序的包名
package main

// 导入其它的包
import "fmt"

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

// 一般类型的声明
type newType int

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

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

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

3.包的导入

  • package 别名与省略调用
// 别名:
import std "fmt"

// 省略调用(这样可以不用写包名,直接调用):
import . "fmt" 

// 初始化,但不调用:
import _ "github.com/go-sql-driver/mysql"
  • 可见性规则
只有首字母为大写的变量、方法、函数等才能被其它包调用(类似面向对象里面的属性public 和private)

二、类型与变量

1.基本类型

类型 长度 默认值 说明
bool 1 false 不能使用0、1代替false、true
byte 1 0 等同于uint8
int、uint 4、8 0 默认整数类型,根据平台,32或64位
int8、uint8 1 0 -128 ~ 127,0 ~ 255
int16、uint16 2 0 -32768 ~ 32767,0 ~ 65535
int32、uint32 4 0 -(2^32 / 2) ~ 2^32 / 2 - 1,0 ~ 2^32
int64、uint64 8 0 -(2^64 / 2) ~ 2^64 / 2 - 1,0 ~ 2^64
float32、float32 4 0.0
float64、float64 8 0.0 默认浮点数类型
complex64 8
complex128 16
rune 4 0 Unicode Code Point, int32
uintptr 4,8 0 足以存储指针的uint
string "" 字符串,默认值为空字符串,而非NULL
array 数组
struct 结构体
function nil 函数
interface nil 接口
map nil 字典,引用类型
slice nil 切片,引用类型
channel nil 通道,引用类型

2.类型别名

设置类型别名后可以让代码可读性更强,一目了然这个变量做什么用的:

type ByteSize int64

func main(){
  var a ByteSize = 1
  fmt.Println(a)
}

这里变量 a 的静态类型是 ByteSize ,底层类型是 int64

3.变量的声明与赋值

  • 变量的声明: var a int
  • 变量的赋值:a = 123
  • 声明并赋值: var a int = 123 (此时若省略类型,则编译器根据值自动推导类型)
  • 多个变量的声明

并行方式(可以省略类型,由值推导)

var a, b, c, int = 1, 2, 3

函数内部声明变量的简写形式:

funciont main(){
	a:= 1
}

函数多个返回值时可以用"_"忽略返回值

 a, _, c, d := 1, 3, 4

4.类型转换

  • go中不存在隐式转换,所有类型转换必须显示声明
  • 转换只能发生在两种相互兼容的类型之间
  • 类型转换的格式:
var a float32 = 1.1
b := int(a)
  • 语法歧义

如果转换的目标是指针、单向通道或没有返回值的函数类型,那么必须使用括号,以避免造成语法分解错误。

fun main() {
	x := 100
	p := *int(&x)   // 错误:cannot convert &x (type *int) to type int
	                // invalid indirect of int(&x) (type int)
	fmt.Println(p)
}

正确的做法是用括号,让编译器将*int解析为指针类型。

(*int)(p)
(<-chan int)(c)
(func())(x)

三、常量与运算符

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 = "456", len(text2),  k* 10
)

2.常量的初始化规则

  • 在定义常量组时,如果不提供初始值,则表示使用上行的表达式
 var a = 1
 const (
    b  = a
    // 此时报错,因为全局变量在编译时不能确定值,常量必须是编译时能确定值的或使用内置函数获得的值(eg:len())
 )
 
 const (
    a = "A"
    b
    c
    // 此时 a,b,c都为"A"
 )
 
 const (
    a, b = 1, "A"
    c, d
    // a,c为1,b,d为"A"。此时注意下行的常量个数必须与上行数量保持一致
 )

3.常量的枚举

  • 使用相同的表达式不代表具有相同的值

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

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

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

const (
    a = "A"
    b
    c = iota
    d        // d的值为3,因为在常量组中,定义了4个变量所以iota计数器从0开始计数4次,所以为3
)

4.运算符

// 优先级从高到低       
 *    /   %   <<  >>  &  &^
 =    +   -   |   ^    
 ==   !=  <   <=  >=  >
 &&
 ||

位的操作:

/*
 6的二进制:0110       第一个
10的二进制:1011       第二个
---------
按位与: &   0010  = 2    (两个都是1才为1)
按位或: |   1111  = 15   (一个是1就是1)
按位异或:^  1101  = 13   (两个只有一个是1才是1)
按位清除:&^ 0100  = 4    (第一个与第二个操作数对应都为1的重置为0,否则与第一位相同)
*/

四、控制语句

1.基础知识补充

指针:

不能将内存地址与指针混为一谈。内存地址是内存中每个字节单元的唯一编号,而指针则是一个实体。指针会分配内存空间,相当于一个专门用来保存地址的整型变量。

func main() {
	x := 100 
	var p *int = &x	// 获取地址,保存到指针变量
	*p += 120       // 用指针间接引用,并更新对象
	println(p, *p)  // 输出指针所存储的地址,以及目标对象
}

输出:

0xc82003df30 220

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

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

  • 默认值为 nil 而非 null

递增递减语句

在go中,++-- 是作为语句而并不是作为表达式

a := 1
a++
// 但不能这样:a := a++,只能作为单独的语句独占一行

2.if 判断语句

  • 条件表达式没有括号

  • 支持一个初始化表达式(可以是并行方式)

  • 左大括号必须和条件语句或else在同一行

  • 支持单行模式

  • 初始化语句中的变量为block级别,同时隐藏外部同名变量

func main(){
  a := 10
  if a:=1 {
      fmt.Println(a)
  }
	fmt.Println(a) 
}
//输出为:  1     10

3.for循环语句

  • go 只有 for 一个循环语句关键字,但支持3种形式
// 第一种(同其他语言的while true {}):
func main() {
  a := 1
  for {
      a++
      if a > 3{
          break
      }
  }
  fmt.Println(a)
}
// 第二种(同其他语言的:while a <= 3 {}):  
func main() {
  a := 1
  for a <= 3 {
     a++
  }
  fmt.Println(a)
}
// 第三种:
func main() {
  a := 1
  for i := 0; i <= 3; i++ {
     a++
  }
  fmt.Println(a)
}
// 第四种:迭代 array、slice、map、chan
func main() {
  a := []int[1,2,3,4,5]
  for k, v := range a {
    fmt.Println(a)
  }
}
  • 初始化和步进表达式可以是多个值

4.switch选择语句

go 语言中无须对每个 case 手动书写 break 以阻止程序继续向下匹配。如果要达到继续匹配的目的可以使用关键字:fallthrough

func main() {
  a := 1
  switch a {
      case 0:
        fmt.Println("a=0")
      case 1:
        fmt.Println("a=1")
  }
  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)
}

//此时a的作用域只在switch表达式之内
func main() {
  
  switch a := 1 {
      case a >= 0:
        fmt.Println("a=0")
        fallthrough
      case a >= 1:
        fmt.Println("a=1")
  }
  fmt.Println(a)
}

5.跳转语句

break、continue、goto 配合标签使用,与其他语言相似