go语言基础知识学习第二天

go语言基础知识学习第二天

          • 运行测试
          • Map(使用 hash 表来实现)
          • 递归函数
          • 语言类型转换
          • 接口
          • 错误处理
          • goroutine 是轻量级线程
          • 通道(channel)
          • 通道缓冲区
          • Go 遍历通道与关闭通道
          • 嵌入类型

运行测试

reverse_test.go

import "testing"

func TestReverse(t *testing.T) {
	cases := []struct {
		in, want string
	}{
		{"Hello, world", "dlrow ,olleH"},
		{"Hello, 世界", "界世 ,olleH"},
		{"", ""},
	}
	for _, c := range cases {
		got := Reverse(c.in)
		if got != c.want {
			t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
		}
	}
}

在当前目录下运行命令 go test

Map(使用 hash 表来实现)

是一种无序的键值对的集合

package main

import "fmt"

func main() {
	var countryCapitalMap map[string]string /*创建集合 */
	countryCapitalMap = make(map[string]string)

	/* map插入key - value对,各个国家对应的首都 */
	countryCapitalMap [ "France" ] = "巴黎"
	countryCapitalMap [ "Italy" ] = "罗马"
	countryCapitalMap [ "Japan" ] = "东京"
	countryCapitalMap [ "India " ] = "新德里"

	/*使用键输出地图值 */
	for country := range countryCapitalMap {
		fmt.Println(country, "首都是", countryCapitalMap [country])
	}

	/*查看元素在集合中是否存在 */
	capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
	/*fmt.Println(capital) */
	/*fmt.Println(ok) */
	if (ok) {
		fmt.Println("American 的首都是", capital)
	} else {
		fmt.Println("American 的首都不存在")
	}
}

delete() 函数用于删除集合的元素

递归函数

阶乘

package main

import "fmt"

func Factorial(n uint64)(result uint64) {
    if (n > 0) {
        result = n * Factorial(n-1)
        return result
    }
    return 1
}

func main() {  
    var i int = 15
    fmt.Printf("%d 的阶乘是 %d\n", i, Factorial(uint64(i)))
}

斐波那契数列

package main

import "fmt"

func Factorial(n uint64)(result uint64) {
    if (n > 0) {
        result = n * Factorial(n-1)
        return result
    }
    return 1
}

func main() {  
    var i int = 15
    fmt.Printf("%d 的阶乘是 %d\n", i, Factorial(uint64(i)))
}
语言类型转换
package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("mean 的值为: %f\n",mean)
}
接口
package main

import "fmt"

type Phone interface {
	call()
}

type ApplePhone struct {
}

func (applePhone ApplePhone) call() {
	fmt.Println("I am apple, I can call you")
}

type IPhone struct {
}

func (iphone IPhone) call() {
	fmt.Println("I am iphone, I can call you!")
}

func main()  {
	var phone Phone
	phone = new(ApplePhone)
	phone.call()

	phone = new(IPhone)
	phone.call()
}
错误处理

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

package main

import (
	"fmt"
)

// 定义一个 DivideError 结构
type DivideError struct {
	dividee int
	divider int
}

// 实现 `error` 接口
func (de *DivideError) Error() string {
	strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
	return fmt.Sprintf(strFormat, de.dividee)
}

// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
	if varDivider == 0 {
		dData := DivideError{
			dividee: varDividee,
			divider: varDivider,
		}
		errorMsg = dData.Error()
		return
	} else {
		return varDividee / varDivider, ""
	}

}

func main() {

	// 正常情况
	if result, errorMsg := Divide(100, 10); errorMsg == "" {
		fmt.Println("100/10 = ", result)
	}
	// 当除数为零的时候会返回错误信息
	if _, errorMsg := Divide(100, 0); errorMsg != "" {
		fmt.Println("errorMsg is: ", errorMsg)
	}

}

goroutine 是轻量级线程

goroutine 的调度是由 Golang 运行时进行管理的
go 函数名(参数列表)

package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i<5; i++ {
		time.Sleep(100 * time.Microsecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	say("hello")
}

通道(channel)
package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // 把 sum 发送到通道 c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := <-c, <-c // 从通道 c 中接收

	fmt.Println(x, y, x+y)
}

另一个示例

package main

import "fmt"

// 不仅可以通过原子函数和互斥锁保证对共享资源的安全访问,消除竞争的状态
// 还可以通过使用通道,在多个goroutine发送和接受共享的数据,达到数据同步的目的

// 使用chan关键字声明一个通道
//ch := make(chan int)

// 还要指定通道中发送和接收数据的类型
//ch <- 2 //发送数值2给这个通道
//x:=<-ch //从通道里读取值,并把读取的值赋值给x变量
//<-ch //从通道里读取值,然后忽略

func main()  {
	ch := make(chan int)

	go func() {
		var sum int = 0
		for i := 0; i < 10; i++ {
			sum += i
		}
		ch <- sum
	}()
	fmt.Println(<-ch)
	// 实现管道效果
	one := make(chan int)
	two := make(chan int)

	go func() {
		one<-100
	}()

	go func() {
		v:=<-one
		two<-v
	}()
	fmt.Println(<-two)
	//mirroredQuery()
}

// 有缓冲通道,其实是一个队列,这个队列的最大容量就是我们使用make函数创建通道时,通过第二个参数指定
//func mirroredQuery() string {
//	response := make(chan string, 3)
//	go func() { response <- request("asia.gopl.io") }()
//	go func() { response <- request("europe.gopl.io") }()
//	go func() { response <- request("americas.gopl.io") }()
//	return <-response
//}
//
//func request(hostname string) (response string) {
//}

// 单向管道
//var send chan<- int //只能发送
//var receive <-chan int //只能接收

通道缓冲区

ch := make(chan int, 100)

package main

import "fmt"

func main() {
    // 这里我们定义了一个可以存储整数类型的带缓冲通道
        // 缓冲区大小为2
        ch := make(chan int, 2)

        // 因为 ch 是带缓冲的通道,我们可以同时发送两个数据
        // 而不用立刻需要去同步读取数据
        ch <- 1
        ch <- 2

        // 获取这两个数据
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}
Go 遍历通道与关闭通道

通过 range 关键字来实现遍历读取到的数据,类似于与数组或切片 v, ok := <-ch

package main

import (
        "fmt"
)

func fibonacci(n int, c chan int) {
        x, y := 0, 1
        for i := 0; i < n; i++ {
                c <- x
                x, y = y, x+y
        }
        close(c)
}

func main() {
        c := make(chan int, 10)
        go fibonacci(cap(c), c)
        // range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个
        // 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据
        // 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不
        // 会结束,从而在接收第 11 个数据的时候就阻塞了。
        for i := range c {
                fmt.Println(i)
        }
}
嵌入类型
package main

import "fmt"

// 嵌入类型
type Reader interface {
	Read(p []byte) (n int, err error)
}

type Writer interface {
	Write(p []byte) (n int, err error)
}

type Closer interface {
	Close() error
}

// 使用组合的形式
type ReadCloser interface {
	Reader
	Closer
}

type WriteClose interface {
	Writer
	Closer
}

type user struct {
	name string
	email string
}

type admin struct {
	user
	level string
}

func main()  {
	ad := admin{user{"solomon", "[email protected]"}, "管理员"}
	// 可以用外部类型直接访问也可以通过内部类型进行访问
	fmt.Println("your username: ", ad.name)
	fmt.Println(ad.user.name)
	fmt.Println(ad.level)
	// 实现接口
	sayHello(ad.user)
	sayHello(ad)
}

type Hello interface {
	hello()
}

func (u user) hello(){
	fmt.Println("Hello, I am a user")
}

func sayHello(h Hello) {
	h.hello()
}

你可能感兴趣的:(go语言基础知识学习第二天)