慕课网Go-4.package、单元测试、并发编程

package

1_1_User.go

go 复制代码
package user

type User struct {
	Name string
}

1_1_UserGet.go

go 复制代码
package user

func GetCourse(c User) string {
	return c.Name
}

1_1_UserMain.go

go 复制代码
package main

import (
	"fmt"
	Userch03 "goproj/IMOOC/ch03/user"//别名,防止同名歧义
)

func main() {
	c := Userch03.User{
		Name: "hi,user",
	}
	fmt.Println(Userch03.GetCourse(c))
}

gin

github链接

go 复制代码
package main

import (
  "net/http"

  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()
  r.GET("/ping", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
      "message": "pong",
    })
  })
  r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

首次使用时,包的导入报错:

鼠标放在"github.com/gin-gonic/gin",出现提示框,点击Sycn...,等一会报错消失

Sync过程自动下载,可以在go.mod中看到

或者在终端打开、go mod tidy

单元测试

go 复制代码
package main

func add(a, b int) int {
	return a + b
}
go 复制代码
package main

import "testing"

func TestAdd(t *testing.T) {
	if testing.Short(){
		t.Skip("short模式")
	}
	re := add(1, 2)
	if re != 3 {
		t.Errorf("expect:%d,actual:%d", 3, re)
	}
}

终端go test

测试函数前的运行箭头右键后

基于表格

go 复制代码
func TestAdd2(t *testing.T) {
	var dataset = []struct {
		a   int
		b   int
		out int
	}{
		{1, 1, 2},
		{-9, 8, 1},
		{0, 0, 0},
	}

	for _, value := range dataset {
		re := add(value.a, value.b)
		if re != value.out {
			t.Errorf("expect:%d,actual:%d", 3, re)
		}
	}
}

性能测试

go 复制代码
const numbers = 10000

func BenchmarkStringSprintf(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		var str string
		for j := 0; j < numbers; j++ {
			str = fmt.Sprintf("%s%d", str, j)
		}
	}
	b.StopTimer()
}

func BenchmarkStringAdd(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		var str string
		for j := 0; j < numbers; j++ {
			str += strconv.Itoa(j)
		}
	}
	b.StopTimer()
}

func BenchmarkStringBuilder(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		var builder strings.Builder
		for j := 0; j < numbers; j++ {
			builder.WriteString(strconv.Itoa(j))
		}
		_ = builder.String()
	}
	b.StopTimer()
}

并发编程

go 复制代码
package main

import (
	"fmt"
	"time"
)

func asyncPrint() {
	time.Sleep(time.Second)
	fmt.Println("hi")
}

func main() {
	go asyncPrint()
	fmt.Println("main")
	time.Sleep(2 * time.Second)
	fmt.Println("main2")
}
go 复制代码
import "fmt"

func main() {

	fmt.Println("method1")
	for i := 0; i < 100; i++ {
		go func() {
			fmt.Println(i)
		}()
	}

	//fmt.Println("method2")
	//for i := 0; i < 100; i++ {
	//	tmp := i
	//	go func() {
	//		fmt.Println(tmp)
	//	}()
	//}

	//fmt.Println("method3")
	//for i := 0; i < 100; i++ {
	//	go func(i int) {
	//		fmt.Println(i)
	//	}(i)
	//}
}

waitgroup

go 复制代码
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	wg.Add(100)
	fmt.Println("method3")
	for i := 0; i < 100; i++ {
		go func(i int) {
			defer wg.Done()
			fmt.Println(i)
		}(i)
	}
	wg.Wait()
}

互斥锁mutex

go 复制代码
package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

var total int32
var wg sync.WaitGroup
var lock sync.Mutex

func add() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		atomic.AddInt32(&total, 1)
		//lock.Lock()
		//total += 1
		//lock.Unlock()
	}
}

func sub() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		atomic.AddInt32(&total, -1)
		//lock.Lock()
		//total -= 1
		//lock.Unlock()
	}
}

func main() {
	wg.Add(2)
	go add()
	go sub()
	wg.Wait()
	fmt.Println(total)
	fmt.Println("all done")
}

读写锁rwlock

go 复制代码
package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var rwlock sync.RWMutex
	var wg sync.WaitGroup

	wg.Add(6)

	//写锁
	go func() {
		time.Sleep(3 * time.Second)
		rwlock.Lock()
		defer rwlock.Unlock()
		fmt.Println("writing")
		time.Sleep(5 * time.Second)
		fmt.Println("write finish")
	}()

	time.Sleep(time.Second)

	//读锁
	for i := 0; i < 5; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 10; j++ {
				rwlock.RLock()
				time.Sleep(500 * time.Millisecond)
				fmt.Println("read")
				rwlock.RUnlock()
			}

		}()
	}
	wg.Wait()
}

channel

go 复制代码
package main

import "fmt"

func main() {
	//有缓存
	var msg1 chan string
	msg1 = make(chan string, 1) //1是缓存空间大小
	msg1 <- "harry"
	data := <-msg1
	fmt.Println(data)
	
	//无缓存,happen-before机制
	var msg2 chan string
	msg2 = make(chan string, 0)
	go func(msg2 chan string) {
		data2 := <-msg2
		fmt.Println(data2)
	}(msg2)
	msg2 <- "potter"
	
	var msg3 chan int
	msg3 = make(chan int, 2)
	go func(msg3 chan int) {
		for data3 := range msg3 {
			fmt.Println(data3)
		}
		fmt.Println("all done")
	}(msg3)
	msg3 <- 1
	msg3 <- 2
	close(msg3)

	var ch1 chan int   //双向
	var ch2 chan<- int //只写入
	var ch3 <-chan int //只读取
	
	c := make(chan int, 3)
	var send chan<- int = c
	var receive <-chan int = c
}

打印数字和字母

go 复制代码
package main

import (
	"fmt"
	"time"
)

var number, letter = make(chan bool), make(chan bool)

func printNum() {
	i := 1
	for {
		<-number
		fmt.Printf("%d%d", i, i+1)
		i += 2
		letter <- true
	}`在这里插入代码片`
}

func printLetter() {
	i := 0
	str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	for {
		<-letter
		if i >= len(str) {
			return
		}
		fmt.Print(str[i : i+2])
		i += 2
		number <- true
	}
}

func main() {
	go printNum()
	go printLetter()
	number <- true
	time.Sleep(100 * time.Second)
}

select

go 复制代码
package main

import (
	"fmt"
	"time"
)

// 空结构体不占内存、channel多线程安全
var done = make(chan struct{})

func g1(ch1 chan struct{}) {
	time.Sleep(time.Second)
	ch1 <- struct{}{}
}

func g2(ch2 chan struct{}) {
	time.Sleep(1 * time.Second)
	ch2 <- struct{}{}
}

func main() {
	ch1 := make(chan struct{})
	ch2 := make(chan struct{})
	go g1(ch1)
	go g2(ch2)

	//执行先就绪的channel,都就绪则随机(防止饥饿)
	//select {
	//case <-ch1:
	//	fmt.Println("g1 done")
	//case <-ch2:
	//	fmt.Println("g2 done")
	//default:
	//	fmt.Println("default")
	//}

	timer := time.NewTimer(5 * time.Second)
	select {
	case <-ch1:
		fmt.Println("g1 done")
	case <-ch2:
		fmt.Println("g2 done")
	case <-timer.C:
		fmt.Println("time our")
		return
	}
}

context

go 复制代码
package main

import (
	"fmt"
	"sync"
	"time"
)

var wgc sync.WaitGroup

func cpuInfo(stop chan struct{}) {
	defer wgc.Done()
	for {
		select {
		case <-stop:
			fmt.Println("退出CPU监控")
			return
		default:
			time.Sleep(2 * time.Second)
			fmt.Println("CPU信息")
		}
	}
}

func main() {
	var stop = make(chan struct{})
	wgc.Add(1)
	go cpuInfo(stop)
	time.Sleep(6 * time.Second)
	stop <- struct{}{}
	wgc.Wait()
	fmt.Println("监控完成")
}
go 复制代码
package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wgc2 sync.WaitGroup

func cpuInfo2(ctx context.Context) {
	defer wgc2.Done()
	for {
		select {
		case <-ctx.Done():
			fmt.Println("退出CPU监控")
			return
		default:
			time.Sleep(2 * time.Second)
			fmt.Println("CPU信息")
		}
	}
}

func main() {
	wgc2.Add(1)
	ctx, cancel := context.WithCancel(context.Background())
	go cpuInfo2(ctx)
	time.Sleep(6 * time.Second)
	cancel()
	wgc2.Wait()
	fmt.Println("监控完成")
}
相关推荐
秋の花6 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端9 分钟前
第六章 7.0 LinkList
java·开发语言·网络
可峰科技18 分钟前
斗破QT编程入门系列之二:认识Qt:编写一个HelloWorld程序(四星斗师)
开发语言·qt
全栈开发圈22 分钟前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫
面试鸭26 分钟前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
小白学大数据27 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
Python大数据分析@30 分钟前
python操作CSV和excel,如何来做?
开发语言·python·excel
上海_彭彭1 小时前
【提效工具开发】Python功能模块执行和 SQL 执行 需求整理
开发语言·python·sql·测试工具·element
334554321 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
沈询-阿里1 小时前
java-智能识别车牌号_基于spring ai和开源国产大模型_qwen vl
java·开发语言