gitalk icon indicating copy to clipboard operation
gitalk copied to clipboard

Go泛型不支持泛型方法,这是一个悲伤的故事

Open utterances-bot opened this issue 3 years ago • 9 comments

Go泛型不支持泛型方法,这是一个悲伤的故事

根据Go 泛型提案的描述,Go不支持泛型方法:No parameterized methods。主要原因Go泛型的处理是在编译的时候实现的,泛型方法在编译的时候,如果没有上下文的分析推断,很难判断泛型方案该如何实例化,甚至判断不了,导致目前(Go 1.18)Go实现中不支

https://colobu.com/2021/12/22/no-parameterized-methods/

utterances-bot avatar Dec 22 '21 06:12 utterances-bot

错字

这也是促进哦把这几天看到的case总结的原因。

r如果是熟悉其它编程语言,

seekdoor avatar Dec 22 '21 06:12 seekdoor

有一点点让人欣慰的是,Ian Lance Taylor和Ian Lance Taylor并没有把话说绝

有处笔误,应为 Ian Lance Taylor和Robert Griesemer

wdvxdr1123 avatar Dec 25 '21 13:12 wdvxdr1123

第一次试用也发现了这个限制,怎么也绕不开。我感觉Facilitator模式也没解决问题,只是把问题甩给了All函数:

func (q *Querier[T]) All(ctx context.Context) ([]T, error) {
	// implementation
       // 除非支持特化,否则这里怎么实现能够返回一个任意的[]T??
}

laizy avatar Jan 27 '22 02:01 laizy

"泛型signleflight" -> "泛型singleflight"

dingyaguang117 avatar Feb 08 '23 11:02 dingyaguang117

其实可以用类似Haskell或者Rust的newtype pattern来凑活,而且由于interface不是单纯的类型类,有可能要当类似rust的trait object来用,所以这个问题其实不好解决。当你需要给一个已有的类型用复杂的带泛型的方法的时候,就把它“lift“到另外一个new type上,通过newtype的泛型来调用泛型方法。当你需要在一个对象上用多个不同的泛型,只需要类型转换一下(大多数情况下是指针,损耗不大)。

type Logic[T any] int

func (self *Logic[T]) sum(xs []T, ops Monoid[T]) T {
	ans := ops.Zero()
	for _, x := range xs {
		ans = ops.Add(ans, x)
	}
	return ans
}
func TestCast() {
	origin_obj := 0
	logic := &origin_obj
	// sum := (*Logic[int])(logic).sum
	(*Logic[int])(logic).sum([]int{1, 2, 3}, new(MonoidInt))
	(*Logic[string])(logic).sum([]string{"fst", "snd"}, new(MonoidString))
}

ireina7 avatar Apr 23 '23 10:04 ireina7

想的我头疼 只能换一种方法泛型了

var ( OK = Code(0, "success") IllegalArgument = Code(100400, "illegal argument") )

type ResponseCode struct { Code int json:"code" Msg string json:"msg" }

func (code *ResponseCode)[T any] ToRsp() AppResponse[T anm] { return Create(code.Code, code.Msg) }

func Code(code int, msg string) *ResponseCode { return &ResponseCode{code, msg} }

jxffly avatar May 26 '23 02:05 jxffly

func ToRsp[T any](code *ResponseCode) AppResponse[T] { return Create(code.Code, code.Msg) }

jxffly avatar May 26 '23 02:05 jxffly

既然举了db的例子,这么做有个非常大的问题是违背了单例模式。比如想生成多个db但底层是一个实例就相当难做(因为每个泛型结构会被当成一个新的实例)。或者也可以投机取巧,在实例的工厂方法里增加一个成员,这个成员是指向底层操作数据库的单例对象的指针。为了保护单例,可以把这个对象做成一个私有接口(含private()空方法就行),别人在包外无法实现。但这样复杂度就相当高了

rainydew avatar Oct 11 '23 04:10 rainydew

真的坑,没有这个能力很多地方做起来太过于麻烦了!

Anthony-Dong avatar Aug 27 '24 04:08 Anthony-Dong