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()
	
}

在这里插入图片描述


延时调用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()
}

在这里插入图片描述


异常处理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


接口编程

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()
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

空接口

在这里插入图片描述

类型断言

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

在这里插入图片描述

在这里插入图片描述

接口编程—电商推荐流程

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

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

  • product.go:商品的信息
package common

type Product struct {
	Id            int
	Name          string
	Size          int
	Sale          int    //销量
	ShipAddress   string //发货地址
	Price         float64
	PositiveRatio float64 //好评率
	RatioCount    int     //评论量
}
  • recaller.go:召回的接口
package recall

import "test10.18/common"

type Recaller interface {
	Recall(n int) []*common.Product
	Name() string
}
  • 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
}
  • 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
}
  • sorter.go:排序的接口
package sort

import "test10.18/common"

type Sorter interface {
	Sort([]*common.Product) []*common.Product
	Name() string
}
  • 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
}
  • 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
}
  • filter.go:过滤的接口
package filter

import "test10.18/common"

// 过滤接口
type Filter interface {
	Filter([]*common.Product) []*common.Product
	Name() string
}
  • 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
}
  • 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)
	}
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天也要写bug、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值