day01go语言基础语法| 青训营笔记

73 阅读8分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

Go笔记

Day_01基础语法

helloWorld

package main
import("fmt")//格式化字符串func main(){
    fmt.Println("hello world")
}

一、变量类型:

类型描述
布尔型布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。
数字类型整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
字符串类型字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
派生类型指针类型(Pointer)、数组类型 、结构化类型(struct) 、 Channel 类型、 函数类型、 切片类型 、接口类型(interface) 、Map 类型

二、变量声明:

指定变量类型,如果没有初始化,则变量默认为零值

根据值自行判定变量类型。

如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误,

:= 相当于是一个声明语句

var name = value
var name,name type = value,value
name := value
//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
​
var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断
​
vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误
​
​
// 这种因式分解关键字的写法一般用于声明全局变量
var (
    vname1 v_type1
    vname2 v_type2
)

值类型和引用类型

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

4.4.2_fig4.1

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

4.4.2_fig4.2

这里可以使用指针进行解释。

三、常量:

将var改成const

const name type = value
//多个常量赋值
const c_name1, c_name2 = value1, value2

你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。

  • 显式类型定义: const b string = "abc"
  • 隐式类型定义: const b = "abc"

常量还可以使用枚举的方式来定义

const{
    Unknown = 0
    Female = 1
    Male = 2
}
iota特殊常量

使用时,从0开始,然后每使用一次就+1,这个常量可以用来被编译器修改的常量值

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

cosnt{
    a = iota//0
    b = iota//1
    c = iota//2
}

四:条件if else:

if 7%2 == 0{
    fmt.println("7 is even")
} else{
    fmt.println("7 is odd")
}
​
if 8%4 == 0{
    fmt.println("8 is divisible by 4")
}
​
if num := 9;num < 0{
    fmt.println(num,"is negative")
} else if num < 10{
    fmt.println(num,"has 1 digit")
} else{
    fmt.println(num,"has multiple digits")
}
​
​

if后面没有括号,写了括号的话,编辑器会自动去除括号,不能将if里面的语句和判断条件写在同一行,if后面必须加{}

五:循环

//死循环
for{}
​
//遍历0到4
for num := 0; num < 5; num++ {
    fmt.println(num)
}
​
for number := 0; number < 5; number++{
    if num % 2 == 0{
        fmt.println(number)
    } 
}
​
i := 0
for i <= 3{
    fmt.println(i)
    i = i + 1
}

只有for循环,没有其他循环,和if语法类似,不需要小括号,必for后面须加{},可以使用continue继续,break跳出

六:分支switch

a := 2
switch a{
    case 1:
        fmt.println("one")
    case 2:
        fmt.println("two")
    case 3:
        fmt.println("three")
    case 4,5:
        fmt.println("four  or five")
    default:
    fmt.println("other")
}
​
t := time.Now()//获取当前时间
switch {
    case t.Hour() < 12:
        fmt.println("morning")
    default:
        fmt.println("afternoon")
}

switch里面的case语句不需要每一行都写break,go语言会自动判定,可以任意变量类型,可以替代if else

七:数组array

//定义数组
var a [5]int//长度为5的一个整型数组

八:切片

不同于数组,是一个可变长度的数组,可以随时变更长度

Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

//定义切片
​
s := make([]string,3)//初始长度为3的一个字符串切片
//给切片赋值,和数组差不多
s[0] = "a"
s[1] = "b"
s[2] = "c"
//遍历切片的值
for i := 0;i < len(s);i++{
    fmt.println(s[i])
}
​
//追加切片并赋值
s = append(s,"d")
s = append(s,"e","f")
fmt.println(s)//[a,b,c,d,e,f]//切片间的赋值
c := make([]string,len[s])
copy(c,s)
fmt.println(c)//[a,b,c,d,e,f]
​
fmt.println(s[2:5])//[c,d,e],从第2个元素开始(不包括第二个)到第5个结束(包括第5个)
fmt.println(s[:5])//[a,b,c,d,e]
fmt.println(s[2:])//[c,d,e,f]

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound]

切片是可索引的,并且可以由 len() 方法获取长度。

切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

九:字典(哈希)map

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

//定义一个map
m := make(map[string]int)//定义一个字符串字典来存放int类型的值
m["one"] = 1
m["two"] = 2
fmt.println(m)
fmt.println(m["one"])
fmt.println(m["unkonwn"])//0
​
r,ok := m["unknown"]//(等于号有判断的作用)判断m中是否含有这个键
fmt.println(r,ok)//0 falsedelete(m,"one")//删除字典m中的键为one的键和值//创建map并赋值
m2 := map[string]int{"one" : 1,"two" : 2}
var m3 = map[string]int{"one" : 1,"two" : 2}
fmt.println(m2,m3)

遍历时完全无序,随机顺序

十:range(排列)

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

array、slice和map可以采用range去遍历

nums := []int{1,2,3,4,5}
sum := 0
//遍历数组
for i,num := range nums{
    sum += num
    if num == 2{
        fmt.println("index:",i,"num:",num)//index1 num:2
    }
}
​
//遍历map
m := map[int]string{1:"A",2:"B",3:"C"}
for i,mValue := range m{
    fmt.println(mValue)
}
​
for k := range m{
    fmt.println("key",k)
}//当只有一个参数时,默认为key

range需要两个参数,第一个是获取的索引,第二个是获取的值

十一:函数

至少有一个main函数,主函数

//定义一个函数
func name([parameter list]) [return_types]{
    函数体
}
//name为函数名,
//parameter list参数列表
//return_types返回类型

go语言函数可以返回多个值

func swap(x,y)(string,string){
    return x,y
}
​
func main(){
    a,b := swap("go","od")
    fmt.println(a,b)
}

函数如果使用参数,该变量可称为函数的形参。

形参就像定义在函数体内的局部变量。

十二:指针

指针使用流程:

  • 定义指针变量。
  • 为指针变量赋值。
  • 访问指针变量中指向地址的值。

&取地址符

*取内容符

//定义一个指针变量
ptr *intfunc add(n int){
    n += 2
}
​
func addPtr(n *int){
    *n += 2
}
​
func main() {
    n := 5
    add(n)
    fmt.println(n)//5
    addPtr(&n)//&取地址符
    fmt.println(n)//7
}

十三:结构体

//定义一个结构体
type user struct{
    name string
    address string
}
​
​

个人理解相当于Java中的实体类,可以结合Java的实体类来学习

结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。

十四:error(错误处理)

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

error类型是一个接口类型,这是它的定义:

type error interface {
    Error() string
}

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) {
    if f < 0 {
        return 0, errors.New("math: square root of negative number")
    }
    // 实现
}

十五:Strings

结合Java的string类来学习。

十六:fmt(格式化)

结合Java中的system.out来学习,大同小异

十七:JSON

对字符串进行序列化

十八:时间处理(time)

进行时间格式化格式不能使用其他语言格式(yyyy-MM-dd hh:mm:ss)而是使用的特定的一个时间(2006-01-02 15:04:05)

now.Unix()获取时间戳的方法

十九:数字解析

使用strconv库,里面的方法可以对数字进行处理

二十:进程信息

使用os库