当前位置: 首页 > news >正文

找人做网站多少钱网建类公司

找人做网站多少钱,网建类公司,wordpress如何上传主题,公司成立费用引子 如果我们要写一个函数分别比较2个整数和浮点数的大小#xff0c;我们就要写2个函数。如下#xff1a; func Min(x, y float64) float64 {if x y {return x}return y }func MinInt(x, y int) int {if x y {return x}return y }2个函数#xff0c;除了数据类…引子 如果我们要写一个函数分别比较2个整数和浮点数的大小我们就要写2个函数。如下 func Min(x, y float64) float64 {if x y {return x}return y }func MinInt(x, y int) int {if x y {return x}return y }2个函数除了数据类型不一样其他处理逻辑完全一言。那有没有方法能一个函数完成上面的功能呢有那就是泛型。 func min2[T int | float64](x, y T) T {if x y {return x}return y }泛型 官网文档https://go.dev/blog/intro-generics 泛型为该语言添加了三个新的重要功能 函数和类型的类型参数。将接口类型定义为类型集包括没有方法的类型。类型推断在许多情况下允许在调用函数时省略类型参数。 类型参数Type Parameters 现在允许函数和类型具有类型参数。类型参数列表看起来与普通参数列表类似只是它使用方括号而不是圆括号。 package mainimport (fmtgolang.org/x/exp/constraints )func GMin[T constraints.Ordered](x, y T) T {if x y {return x}return y }func main() {x : GMin[int](2, 3)fmt.Println(x) // 输出结果为2 } 其中constraints.Ordered是自定义类型这里不展示源码。 理解不了的可以暂时把constraints.Ordered替换为 int | float64。 向 GMin 提供类型参数在本例中为 int称为实例化instantiation。实例化分两步进行。 首先编译器在整个泛型函数或类型中将所有类型实参替换为其各自的类型参数。其次编译器验证每个类型参数是否满足各自的约束。 成功实例化后我们有一个非泛型函数可以像任何其他函数一样调用它。例如在类似的代码中 fmin : GMin[float64] m : fmin(2.71, 3.14)全部代码为 package mainimport (fmtgolang.org/x/exp/constraints )func GMin[T constraints.Ordered](x, y T) T {if x y {return x}return y }func main() {fmin : GMin[float64] // 相当于func GMin(x, y float64) float64{...}m : fmin(2.71, 3.14)fmt.Println(m) // 输出结果为2.71 } 实例化 GMin[float64] 生成的实际上是我们原始的浮点 Min 函数我们可以在函数调用中使用它。 类型参数也可以与类型一起使用。 type Tree[T interface{}] struct {left, right *Tree[T]value T }func (t *Tree[T]) Lookup(x T) *Tree[T] { ... }var stringTree Tree[string]这里泛型类型 Tree 存储类型参数 T 的值。泛型类型可以有方法就像本例中的 Lookup 一样。为了使用泛型类型必须对其进行实例化 Tree[string] 是使用类型参数 string 实例化 Tree 的示例。 类型集Type sets 类型参数列表中的每个类型参数都有一个类型。由于类型参数本身就是一种类型因此类型参数的类型定义了类型集。这种元类型称为类型约束。 在泛型方法GMin 中类型约束是从约束包中导入的。 Ordered 约束描述了具有可排序值的所有类型的集合或者换句话说与 运算符或 、 等进行比较。该约束确保只有具有可排序值的类型才能传递给 GMin。这也意味着在 GMin 函数体中该类型参数的值可以用于与 运算符进行比较。 在 Go 中类型约束必须是接口。也就是说接口类型可以用作值类型value type也可以用作元类型meta-type。 接口作为值类型 当接口用作值类型时它定义了一组方法任何实现了这些方法的类型都可以赋值给这个接口变量。这是接口最常见的用法。 例如 type Stringer interface {String() string }type Person struct {Name string }func (p Person) String() string {return p.Name }var s Stringer Person{Alice} // Person 实现了 Stringer 接口 fmt.Println(s.String()) // 输出: Alice在这个例子中Stringer 接口被用作值类型Person 类型实现了 String() 方法因此可以赋值给 Stringer 类型的变量。 接口作为元类型meta-type 当接口用作元类型时它定义了一组类型约束用于泛型编程。 例如 type Ordered interface {int | float64 | string }func Min[T Ordered](a, b T) T {if a b {return a}return b }fmt.Println(Min(3, 5)) // 输出: 3 fmt.Println(Min(3.14, 2.71)) // 输出: 2.71 fmt.Println(Min(a, b)) // 输出: a在这个例子中Ordered 接口被用作元类型它定义了一组可以进行比较操作的类型整数、浮点数和字符串。Min 函数使用这个接口作为类型约束可以接受任何满足 Ordered 约束的类型作为参数。 它们不仅可以定义对象的行为作为值类型还可以定义类型集合作为元类型从而在保持语言简洁性的同时大大增强了代码的表达能力和复用性。 直到最近Go 规范还说接口定义了一个方法集大致就是接口中枚举的方法集。任何实现所有这些方法的类型都实现该接口。 但看待这个问题的另一种方式是说接口定义了一组类型即实现这些方法的类型。从这个角度来看作为接口类型集元素的任何类型都实现该接口。 这两种视图导致相同的结果对于每组方法我们可以想象实现这些方法的相应类型集即由接口定义的类型集。 不过就我们的目的而言类型集视图比方法集视图有一个优势我们可以显式地将类型添加到集合中从而以新的方式控制类型集。 我们扩展了接口类型的语法来实现这一点。例如interface{ int|string|bool } 定义了包含 int、string 和 bool 类型的类型集。 另一种说法是该接口仅由 int、string 或 bool 满足。 现在让我们看看constraints.Ordered的实际定义 type Ordered interface {Integer|Float|~string }该声明表示 Ordered 接口是所有整数、浮点和字符串类型的集合。竖线表示类型的联合或本例中的类型集。 Integer 和 Float 是在约束包中类似定义的接口类型。请注意Ordered 接口没有定义任何方法。 对于类型约束我们通常不关心具体的类型比如字符串我们对所有字符串类型都感兴趣。这就是 ~ 令牌的用途。表达式 ~string 表示基础类型为 string 的所有类型的集合。这包括类型 string 本身以及使用定义声明的所有类型例如type MyString string 当然我们还是想在接口中指定方法并且我们希望能够向后兼容。在 Go 1.18 中接口可以像以前一样包含方法和嵌入接口但它也可以嵌入非接口类型、联合和底层类型集。 用作约束的接口可以指定名称例如 Ordered也可以是内联在类型参数列表中的文字接口。例如 [S interface{~[]E}, E interface{}]这里S必须是一个切片类型其元素类型可以是任何类型。 因为这是常见的情况所以对于约束位置的接口可以省略封闭的interface{}我们可以简单地编写(Go 语言中泛型的语法糖和类型约束的简化写法) [S ~[]E, E interface{}]由于空接口在类型参数列表以及普通 Go 代码中很常见因此 Go 1.18 引入了一个新的预声明标识符 any 作为空接口类型的别名。这样我们就得到了这个惯用的代码 [S ~[]E, E any]在使用类型约束时如果省略了外层的interface{}会引起歧义那么就不能省略。例如 type IntPtrSlice1 [T * int][]T // 错误这里会把*误会为乘号 type IntPtrSlice2[T *int,] []T // 正确只有一个类型约束时可以添加, type IntPtrSlice3[T interface{ *int }] []T // 正确使用interface{}包裹 type IntPtrSlice4[T *int, T2 *int] []T // 正确只有IntPtrSlice1是语法错误的IntPtrSlice2-4语法正确 类型推断Type inference 函数参数类型推断 有了类型参数就需要传递类型参数这可能会导致代码冗长。回到我们的通用 GMin 函数 func GMin[T constraints.Ordered](x, y T) T { ... }类型参数 T 用于指定普通非类型参数 x 和 y 的类型。正如我们之前看到的可以使用显式类型参数来调用它 var a, b, m float64m GMin[float64](a, b) // explicit type argument在许多情况下编译器可以从普通参数推断出 T 的类型参数。这使得代码更短同时保持清晰。 var a, b, m float64m GMin(a, b) // no type argument这是通过将参数 a 和 b 的类型与参数 x 和 y 的类型进行匹配来实现的。 这种从函数参数的类型推断出参数类型的推断称为函数参数类型推断。 约束类型推断 该语言支持另一种类型推断即约束类型推断。为了描述这一点让我们从缩放整数切片的示例开始 // Scale returns a copy of s with each element multiplied by c. // This implementation has a problem, as we will see. func Scale[E constraints.Integer](s []E, c E) []E {r : make([]E, len(s))for i, v : range s {r[i] v * c}return r }这是一个通用函数适用于任何整数类型的切片。 现在假设我们有一个多维 Point 类型其中每个 Point 只是给出点坐标的整数列表。这种类型自然会有一些方法。 type Point []int32func (p Point) String() string {// Details not important. }有时我们想要缩放一个点。由于 Point 只是整数切片因此我们可以使用之前编写的 Scale 函数 // ScaleAndPrint doubles a Point and prints it. func ScaleAndPrint(p Point) {r : Scale(p, 2)fmt.Println(r.String()) // DOES NOT COMPILE }这无法编译失败并出现类似 r.String undefined (type []int32 has no field or method String) 的错误。 完整代码见https://gitee.com/qingfeng-169/blog-code/blob/master/csdn/generics/demo1/main.go 问题在于Scale(p, 2)相当于Scale[int32](p, 2)Scale 函数返回 []E 类型的值其中 E 是参数切片的元素类型这里是int32。当我们使用 Point 类型的值其基础类型为 []int32调用 Scale 时我们返回的是 []int32 类型的值而不是 Point 类型。这是通用代码的编写方式所遵循的但这不是我们想要的。 为了解决这个问题我们必须更改 Scale 函数以使用切片类型的类型参数。 // Scale returns a copy of s with each element multiplied by c. func Scale[S ~[]E, E constraints.Integer](s S, c E) S {r : make(S, len(s))for i, v : range s {r[i] v * c}return r }我们引入了一个新的类型参数 S它是切片参数的类型。我们对其进行了约束使基础类型为 S 而不是 []E结果类型现在为 S。由于 E 被约束为整数因此效果与之前相同第一个参数必须是某种整数类型的切片。函数体的唯一变化是现在当我们调用 make 时我们传递 S而不是 []E。 有助于理解的代码https://gitee.com/qingfeng-169/blog-code/blob/master/csdn/generics/demo2/main.go 完整代码见https://gitee.com/qingfeng-169/blog-code/blob/master/csdn/generics/demo3/main.go 有助于理解的代码https://gitee.com/qingfeng-169/blog-code/blob/master/csdn/generics/demo4/main.go 但我们可以公平地问为什么可以在不传递显式类型参数的情况下编写对 Scale 的调用也就是说为什么我们可以编写没有类型参数的 Scale(p, 2)而不是必须编写 Scale[Point, int32](p, 2)我们的新 Scale 函数有两个类型参数S 和 E。在不传递任何类型参数的 Scale 调用中如上所述的函数参数类型推断可以让编译器推断 S 的类型参数是 Point。但该函数还有一个类型参数 E它是乘法因子 c 的类型。对应的函数参数是 2并且由于 2 是无类型常量因此函数参数类型推断无法推断出 E 的正确类型最多可能推断出 2 的默认类型为 int这是不正确的。相反编译器推断 E 的类型参数是切片的元素类型的过程称为约束类型推断。 约束类型推断从类型参数约束中推导出类型实参。当一个类型参数具有根据另一类型参数定义的约束时使用它。当这些类型参数之一的类型参数已知时约束用于推断另一个类型参数的类型参数。 应用这种情况的通常情况是当一个约束对某种类型使用 ~type 形式其中该类型是使用其他类型参数编写的。我们在 Scale 示例中看到了这一点。 S 是 ~[]E即 ~ 后跟根据另一个类型参数编写的类型 []E。如果我们知道 S 的类型参数我们就可以推断出 E 的类型参数。S 是切片类型E 是该切片的元素类型。 这只是对约束类型推断的介绍。有关完整详细信息请参阅提案文档或语言规范。
http://www.w-s-a.com/news/900175/

相关文章:

  • 深圳网站建设排名做网站的公司高创
  • 杭州哪家做外贸网站全国物流网站有哪些平台
  • 企业网站建设个人博客鞍山晟宇网站建设
  • 广东省自然资源厅网站h5移动端网站模板下载
  • 网站建设和安全管理制度云南九泰建设工程有限公司官方网站
  • 网站的关键词和描述做外贸家纺资料网站
  • 绥化市建设工程网站招投标地址链接怎么生成
  • 网站制作设计发展前景网页链接制作生成二维码
  • 廊坊哪里有制作手机网站的企业网站建设费用财务处理
  • 手机网站建设书籍工商咨询服务
  • 麻花星空影视传媒制作公司网站美食网站网站建设定位
  • 网站的切图是谁来做学会网站 建设
  • 交通局网站建设方案答辩ppt模板免费下载 素材
  • 个人摄影网站推介网手机版
  • 有哪些免费的视频网站网站开发和竞价
  • 学校网站如何做广州商城型网站建设
  • 微网站建设哪家便宜易优建站系统
  • 推荐做木工的视频网站毕业设计做的网站抄袭
  • 网站导航页面制作wordpress调用文章阅读量
  • app小程序网站开发品牌购物网站十大排名
  • 用wordpress做购物网站龙岩品牌设计
  • 网站开发是指wordpress系统在线升级
  • 网站建设运营的灵魂是什么意思页面跳转中
  • 家政服务网站源码重庆建网站企业有哪些
  • 怎样分析一个网站做的好坏重庆长寿网站设计公司哪家专业
  • 百度助手app下载苏州seo关键词优化排名
  • 17网站一起做 佛山诸城网站建设多少钱
  • 郑州网站建设培训学校泉州做网站设计公司
  • 西峡做网站深圳建筑工务署官网
  • 单县网站惠州seo计费