• Go语言函数基础



    函数传参

    值传递

    如果函数的参数是值传递,那么参数就是实参的一份拷贝。
    比如函数的参数是一个数组,那么该数组就是源数组的拷贝。
    如果是一个切片,那么该切片也是源切片的拷贝,但是这俩切片的指针指向同一块空间,所以可以通过形参修改源切片中数组的值,但是不能修改源切片的成员信息,比如len和cap。
    在这里插入图片描述

    如果是传指针的话,则可以修改实参
    在这里插入图片描述

    不定长参数

    函数的参数可以是不定长参数,这些参数会以切片的形式进行传入。
    在这里插入图片描述

    函数作为数据类型和匿名函数

    在go语言中函数也被当做一种数据类型。
    在这里插入图片描述
    在这里插入图片描述


    闭包

    闭包有点类似于C++中static修饰局部变量,都是延长变量的生命周期。
    在这里插入图片描述

    func sub() func() {
    	i := 10
    	fmt.Println(&i)
    	b := func() {
    		fmt.Println(&i) //闭包中复制了i的指针
    		i--             //在b函数中引用了变量i
    		fmt.Println(i)
    	}
    	return b
    }
    func main() {
    	b := sub()
    	b()
    	b()
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述


    延时调用defer

    在这里插入图片描述

    func defer_exe_time() (i int) {
    	i = 9
    	defer func() {
    		fmt.Printf("1 i=%d\n", i)//i是返回时的i,也就是5
    	}()
    	defer func(i int) {
    		fmt.Printf("2 i=%d\n", i)//i是注册时的i
    	}(i)
    	defer fmt.Printf("3 i=%d\n", i) //9
    	return 5
    }
    func main() {
    	defer_exe_time()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述


    异常处理

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述


    接口编程

    go语言中没有C++中继承和多态等机制,它通过接口来实现多态。

    在这里插入图片描述

    一个结构体只要实现了接口中的方法,这个结构体就可以被这个接口对象赋值。
    接口指向不同的结构体,就可以实现多态的功能。

    type Transporter interface {
    	move(int, int) (int, error)
    	whilst() error
    }
    type A interface {
    	goo()
    	Transporter //继承Transporter接口
    }
    type Car struct {
    	price int
    	power float32
    }
    
    func (car Car) whilst() error {
    	fmt.Println("whilst")
    	fmt.Printf("价格:%d,动力:%f\n", car.price, car.power)
    	return errors.New("123")
    }
    func (car Car) move(a int, b int) (int, error) {
    	return a + b, nil
    }
    func (car Car) walk() {
    	fmt.Println("I'm walking")
    }
    func (car Car) goo() {
    	fmt.Println("I'm going")
    
    }
    func main() {
    	var ifc Transporter
    	c := Car{10, 1.1}
    	ifc = &c
    	ifc.whilst()
    	ifc.move(1, 2)
    
    	c.whilst()
    	c.move(1, 2)
    
    	var a A
    	a = c
    	a.goo()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    空接口

    在这里插入图片描述

    类型断言

    由于空接口可以传入任意类型的数据,所以就需要类型断言来判断传入的数据类型。

    在这里插入图片描述

    在这里插入图片描述

    接口编程—电商推荐流程

    电商推荐流程如下:首先会按照商品的属性进行召回商品,然后根据商品的属性进行排序,再过滤掉不符合要求的商品。召回和过滤有多个,所以我们可以采用接口来实现。

    在这里插入图片描述

    在这里插入图片描述

    推荐引擎,里面是接口的切片:

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    下面是该商品推荐系统的结构:
    在这里插入图片描述

    • product.go:商品的信息
    package common
    
    type Product struct {
    	Id            int
    	Name          string
    	Size          int
    	Sale          int    //销量
    	ShipAddress   string //发货地址
    	Price         float64
    	PositiveRatio float64 //好评率
    	RatioCount    int     //评论量
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • recaller.go:召回的接口
    package recall
    
    import "test10.18/common"
    
    type Recaller interface {
    	Recall(n int) []*common.Product
    	Name() string
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • hot_recall.go:按照热度召回
    package recall
    
    import (
    	"sort"
    	"test10.18/common"
    )
    
    var allProducts = []*common.Product{
    	{Id: 1, Size: 100, Sale: 38, Name: "p1"},
    	{Id: 2, Size: 1000, Sale: 44, Name: "p2"},
    	{Id: 3, Size: 50, Sale: 555, Name: "p3"},
    	{Id: 4, Size: 105, Sale: 11, Name: "p4"},
    	{Id: 5, Size: 20, Sale: 2, Name: "p5"},
    	{Id: 6, Size: 1550, Sale: 888, Name: "p6"},
    	{Id: 7, Size: 1250, Sale: 9999, Name: "p7"},
    	{Id: 8, Size: 1240, Sale: 444, Name: "p8"},
    	{Id: 9, Size: 1201, Sale: 11, Name: "p9"},
    	{Id: 10, Size: 1052, Sale: 10000, Name: "p10"},
    }
    
    // 按照热度召回
    type HotRecall struct {
    	Tag string
    }
    
    func (r HotRecall) Name() string {
    	return r.Tag
    }
    func (r HotRecall) Recall(n int) []*common.Product {
    	sort.Slice(allProducts, func(i, j int) bool {
    		//销量从大到小排序
    		return allProducts[i].Sale > allProducts[j].Sale
    	})
    	rect := make([]*common.Product, 0, n)
    	for _, product := range allProducts {
    		rect = append(rect, product)
    		if len(rect) >= n {
    			break
    		}
    	}
    	return rect
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • size_recall.go:按照商品的尺寸进行召回
    package recall
    
    import (
    	"test10.18/common"
    )
    
    // 按照热度召回
    type SizeRecall struct {
    	Tag string
    }
    
    func (r SizeRecall) Name() string {
    	return r.Tag
    }
    func (r SizeRecall) Recall(n int) []*common.Product {
    	//将size小于200的商品进行召回
    	rect := make([]*common.Product, 0, n)
    	for _, product := range allProducts {
    		if product.Size < 200 {
    			rect = append(rect, product)
    			if len(rect) >= n {
    				break
    			}
    		}
    	}
    	return rect
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • sorter.go:排序的接口
    package sort
    
    import "test10.18/common"
    
    type Sorter interface {
    	Sort([]*common.Product) []*common.Product
    	Name() string
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • ratio_sorter.go:按照热度进行排序
    package sort
    
    import (
    	"sort"
    	"test10.18/common"
    )
    
    type RatioSorter struct {
    	Tag string
    }
    
    func (self RatioSorter) Name() string {
    	return self.Tag
    }
    func (self RatioSorter) Sort(products []*common.Product) []*common.Product {
    	sort.Slice(products, func(i, j int) bool {
    		return products[i].PositiveRatio > products[j].PositiveRatio
    	})
    	return products
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • size_sorter.go:按照大小进行排序
    package sort
    
    import (
    	"sort"
    	"test10.18/common"
    )
    
    type SizeSorter struct {
    	Tag string
    }
    
    func (self SizeSorter) Name() string {
    	return self.Tag
    }
    func (self SizeSorter) Sort(products []*common.Product) []*common.Product {
    	sort.Slice(products, func(i, j int) bool {
    		return products[i].Size > products[j].Size
    	})
    	return products
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • filter.go:过滤的接口
    package filter
    
    import "test10.18/common"
    
    // 过滤接口
    type Filter interface {
    	Filter([]*common.Product) []*common.Product
    	Name() string
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • ratio_filter.go:按照热度过滤的接口
    package filter
    
    import "test10.18/common"
    
    type RatioFilter struct {
    	Tag string
    }
    
    func (self RatioFilter) Name() string {
    	return self.Tag
    }
    func (self RatioFilter) Filter(products []*common.Product) []*common.Product {
    	rect := make([]*common.Product, 0, len(products))
    	for _, product := range products {
    		if product.RatioCount >= 0 && product.PositiveRatio >= 0 {
    			rect = append(rect, product)
    		}
    	}
    	return rect
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • rec.go:召回商品
    package main
    
    import (
    	"fmt"
    	"log"
    	"test10.18/common"
    	"test10.18/filter"
    	"test10.18/recall"
    	"test10.18/sort"
    	"time"
    )
    
    type Recommender struct {
    	Recallers []recall.Recaller
    	Sorter    sort.Sorter
    	Filters   []filter.Filter
    }
    
    func (rec *Recommender) Rec() []*common.Product {
    	RecallMap := make(map[int]*common.Product, 100)
    	//顺序遍历每一路的召回
    	for _, recaller := range rec.Recallers {
    		begin := time.Now()
    		products := recaller.Recall(10)
    		log.Printf("召回%s耗时%dns,召回了%d个商品\n", recaller.Name(), time.Since(begin).Nanoseconds(), len(products))
    		for _, product := range products {
    			RecallMap[product.Id] = product
    		}
    	}
    	log.Printf("一共召回了%d个商品\n", len(RecallMap))
    	RecallSice := make([]*common.Product, 0, len(RecallMap))
    	for _, product := range RecallMap {
    		RecallSice = append(RecallSice, product)
    	}
    	//召回完以后,对召回结果进行排序
    	begin := time.Now()
    	SortedResult := rec.Sorter.Sort(RecallSice)
    	log.Printf("排序耗时%dns\n", time.Since(begin).Nanoseconds())
    
    	//排完序以后进行过滤
    	FilteredResult := SortedResult
    	prevCount := len(FilteredResult)
    	for _, filter := range rec.Filters {
    		begin := time.Now()
    		FilteredResult = filter.Filter(FilteredResult)
    		log.Printf("过滤规则%s耗时%dns,过滤掉了%d个商品\n", filter.Name(), time.Since(begin).Nanoseconds(), prevCount-len(FilteredResult))
    		prevCount = len(FilteredResult)
    	}
    	return FilteredResult
    }
    func main() {
    	recer := Recommender{
    		Recallers: []recall.Recaller{
    			recall.HotRecall{"hot"},
    			recall.SizeRecall{"size"},
    		},
    		Sorter: sort.RatioSorter{Tag: "tatio"},
    		Filters: []filter.Filter{
    			filter.RatioFilter{"ratio"},
    		},
    	}
    	result := recer.Rec()
    	for i, product := range result {
    		fmt.Printf("第%d名:%d %s\n", i, product.Id, product.Name)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    运行结果:
    在这里插入图片描述

  • 相关阅读:
    表达式求值的相关语法知识(C语言)
    教育培训机构投诉无果?中创教育说试试这样维权
    Spring MVC如何进行重定向呢?
    FOC程序算法编写
    网络安全(黑客)技术自学
    git命令整理
    【6】uniform颜色写入
    数据结构:循环队列
    SPSS到底怎么入门?这些干货你收藏了么?
    MeterSphere 任意文件读取漏洞(CVE-2023-25814)
  • 原文地址:https://blog.csdn.net/qq_52670477/article/details/127395454