go语言学习笔记

学习笔记参考链接
学习笔记参考链接
学习笔记参考链接

结构体

package main

import (  
    "fmt"
)

type Employee struct {  
    firstName, lastName string
    age, salary         int
}

func main() {

    //creating structure using field names
    emp1 := Employee{
        firstName: "Sam",
        age:       25,
        salary:    500,
        lastName:  "Anderson",
    }

    //creating structure without using field names
    emp2 := Employee{"Thomas", "Paul", 29, 800}

    fmt.Println("Employee 1", emp1)
    fmt.Println("Employee 2", emp2)
}

在上述程序的第 7 行,我们创建了一个命名的结构体 Employee。而在第 15 行,通过指定每个字段名的值,我们定义了结构体变量 emp1。字段名的顺序不一定要与声明结构体类型时的顺序相同。在这里,我们改变了 lastName 的位置,将其移到了末尾。这样做也不会有任何的问题。

输出结构体1结构体2的值
Employee 1 {Sam Anderson 25 500}
Employee 2 {Thomas Paul 29 800}

指针

是什么
变量 b 的值为 156,而 b 的内存地址为 0x1040a124。变量 a 存储了 b 的地址。我们就称 a 指向了 b。
指针变量的类型为 *T,该指针指向一个 T 类型的变量

package main

import (
    "fmt"
)

func main() {
    b := 255
    var a *int = &b
    fmt.Printf("Type of a is %T\n", a)
    fmt.Println("address of b is", a)
}

解引用

package main  
import (  
    "fmt"
)

func main() {  
    b := 255
    a := &b
    fmt.Println("address of b is", a)
    fmt.Println("value of b is", *a)
}

输出
address of b is 0x1040a124
value of b is 255

常量

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

package main
import "fmt"
const (
	a = 1
	b
	c
	d
)
func main() {
	fmt.Println(a)
	// b、c、d没有初始化,使用上一行(即a)的值
	fmt.Println(b)   // 输出1
	fmt.Println(c)   // 输出1
	fmt.Println(d)   // 输出1
}

iota是常量的计数器,从0开始,组中每定义一个常量,自动递增1.
通过初始化规则与iota可以达到枚举的效果
每遇到一个const关键字,iota就会重置为0

package main
import "fmt"
const (
	a = "ast"
	b = "bst"
	c = iota
	d
)
func main() {
	fmt.Println(a)   // ast
	fmt.Println(b)   // bst
	// c=iota, iota从0开始,组中每定义一个常量自动递增1,在本组中,c之前定义了2个常量,
	// 所以iota增加了2,即:iota = 2
	fmt.Println(c)   // 2
	// 枚举效果
	fmt.Println(d)   // 3
}


type

1.定义结构体
2.类型等价定义,相当于类型重命名

type name string
name类型与string等价

type name string

func main() {
var myname name = "taozs" //其实就是字符串类型
l := []byte(myname)       //字符串转字节数组
fmt.Println(len(l))       //字节长度
}

rang

range函数是个神奇而有趣的内置函数,你可以使用它来遍历数组,切片和字典。

当用于遍历数组和切片的时候,range函数返回索引和元素;

当用于遍历字典的时候,range函数返回字典的键和值。

package main

import "fmt"

func main() {

    // 这里我们使用range来计算一个切片的所有元素和
    // 这种方法对数组也适用
    nums := []int{2, 3, 4}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:", sum)

    // range 用来遍历数组和切片的时候返回索引和元素值
    // 如果我们不要关心索引可以使用一个下划线(_)来忽略这个返回值
    // 当然我们有的时候也需要这个索引
    for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
    }

    // 使用range来遍历字典的时候,返回键值对。
    kvs := map[string]string{"a": "apple", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }

    // range函数用来遍历字符串时,返回Unicode代码点。
    // 第一个返回值是每个字符的起始字节的索引,第二个是字符代码点,
    // 因为Go的字符串是由字节组成的,多个字节组成一个rune类型字符。
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}

输出结果
sum: 9
index: 1
a -> apple
b -> banana
0 103
1 111

方法

方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。

Go 不是纯粹的面向对象编程语言,而且Go不支持类。因此,基于类型的方法是一种实现和类相似行为的途径。

package main

import (
    "fmt"
)

type Employee struct {
    name     string
    salary   int
    currency string
}

/*
  displaySalary() 方法将 Employee 做为接收器类型
*/
func (e Employee) displaySalary() {
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {
    emp1 := Employee {
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    emp1.displaySalary() // 调用 Employee 类型的 displaySalary() 方法
}

指针接收器与值接收器

package main

import (
    "fmt"
)

type Employee struct {
    name string
    age  int
}

/*
使用值接收器的方法。
*/
func (e Employee) changeName(newName string) {
    e.name = newName
}

/*
使用指针接收器的方法。
*/
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}

func main() {
    e := Employee{
        name: "Mark Andrew",
        age:  50,
    }
    fmt.Printf("Employee name before change: %s", e.name)
    e.changeName("Michael Andrew")
    fmt.Printf("\nEmployee name after change: %s", e.name)

    fmt.Printf("\n\nEmployee age before change: %d", e.age)
    (&e).changeAge(51)
    fmt.Printf("\nEmployee age after change: %d", e.age)
}

函数

函数的声明以关键词 func 开始,后面紧跟自定义的函数名 functionname (函数名)。函数的参数列表定义在 ( 和 ) 之间,返回值的类型则定义在之后的 returntype (返回值类型)处。声明一个参数的语法采用 参数名 参数类型 的方式,任意多个参数采用类似 (parameter1 type, parameter2 type) 即(参数1 参数1的类型,参数2 参数2的类型)的形式指定。之后包含在 { 和 } 之间的代码,就是函数体。

func functionname(parametername type) returntype {  
    // 函数体(具体实现的功能)
}

多返回值
我们继续以 rectProps 函数为例,该函数计算的是面积和周长。假使我们只需要计算面积,而并不关心周长的计算结果,该怎么调用这个函数呢?这时,空白符 _ 就上场了

package main

import (  
    "fmt"
)

func rectProps(length, width float64) (float64, float64) {  
    var area = length * width
    var perimeter = (length + width) * 2
    return area, perimeter
}
func main() {  
    area, _ := rectProps(10.8, 5.6) // 返回值周长被丢弃
    fmt.Printf("Area %f ", area)
}

数组和切片

切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用。
创建切片方法一

package main

import (
    "fmt"
)

func main() {
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:4] // creates a slice from a[1] to a[3]
    fmt.Println(b)
}

使用语法 a[start:end] 创建一个从 a 数组索引 start 开始到 end - 1 结束的切片。因此,在上述程序的第 9 行中, a[1:4] 从索引 1 到 3 创建了 a 数组的一个切片表示。因此, 切片 b 的值为 [77 78 79]。

创建切片方法二

package main

import (  
    "fmt"
)

func main() {  
    c := []int{6, 7, 8} // creates and array and returns a slice reference
    fmt.Println(c)
}

在上述程序的第 9 行,c:= [] int {6,7,8} 创建一个有 3 个整型元素的数组,并返回一个存储在 c 中的切片引用

切片的长度和容量

切片的长度是切片中的元素数。切片的容量是从创建切片索引开始的底层数组中元素数

package main

import (
    "fmt"
)

func main() {
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) // length of is 2 and capacity is 6
}

在上面的程序中,fruitslice 是从 fruitarray 的索引 1 和 2 创建的。 因此,fruitlice 的长度为 2。
fruitarray 的长度是 7。fruiteslice 是从 fruitarray 的索引 1 创建的。因此, fruitslice 的容量是从 fruitarray 索引为 1 开始,也就是说从 orange 开始,该值是 6。因此, fruitslice 的容量为 6。该程序输出切片的 长度为 2 容量为 6 。

使用 make 创建一个切片
func make([]T,len,cap)[]T 通过传递类型,长度和容量来创建切片。容量是可选参数, 默认值为切片长度。make 函数创建一个数组,并返回引用该数组的切片。

package main

import (
    "fmt"
)

func main() {
    i := make([]int, 5, 5)
    fmt.Println(i)
}

使用 make 创建切片时默认情况下这些值为零。上述程序的输出为 [0 0 0 0 0]

追加切片元素
正如我们已经知道数组的长度是固定的,它的长度不能增加。 切片是动态的,使用 append 可以将新元素追加到切片上。append 函数的定义是 func append(s[]T,x … T)[]T。
当新的元素被添加到切片时,会创建一个新的数组。现有数组的元素被复制到这个新数组中,并返回这个新数组的新切片引用。现在新切片的容量是旧切片的两倍。

package main

import (
    "fmt"
)

func main() {
    cars := []string{"Ferrari", "Honda", "Ford"}
    fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) // capacity of cars is 3
    cars = append(cars, "Toyota")
    fmt.Println("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) // capacity of cars is doubled to 6
}

在上述程序中,cars 的容量最初是 3。在第 10 行,我们给 cars 添加了一个新的元素,并把 append(cars, “Toyota”) 返回的切片赋值给 cars。现在 cars 的容量翻了一番,变成了 6。上述程序的输出是
cars: [Ferrari Honda Ford] has old length 3 and capacity 3
cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6

切片类型的零值为 nil。一个 nil 切片的长度和容量为 0。可以使用 append 函数将值追加到 nil 切片。

package main

import (  
    "fmt"
)

func main() {  
    var names []string //zero value of a slice is nil
    if names == nil {
        fmt.Println("slice is nil going to append")
        names = append(names, "John", "Sebastian", "Vinay")
        fmt.Println("names contents:",names)
    }
}

在上面的程序 names 是 nil,我们已经添加 3 个字符串给 names。该程序的输出是
slice is nil going to append
names contents: [John Sebastian Vinay]

也可以使用 … 运算符将一个切片添加到另一个切片

package main

import (
    "fmt"
)

func main() {
    veggies := []string{"potatoes", "tomatoes", "brinjal"}
    fruits := []string{"oranges", "apples"}
    food := append(veggies, fruits...)
    fmt.Println("food:",food)
}

在上述程序的第 10 行,food 是通过 append(veggies, fruits…) 创建。程序的输出为 food: [potatoes tomatoes brinjal oranges apples]。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值