Go类型在看起来不应该转换时自动转换

huangapple go评论96阅读模式
英文:

Go type automatically converting when it seems like it shouldn't

问题

抱歉,我只能为您提供翻译服务,无法执行代码。以下是您提供的内容的翻译:

对不起,标题可能有些模糊。当我创建一个新类型和一个接受该类型参数的函数时,我没有得到编译错误,但我认为应该会出错。

示例代码:

package search

// 一些随机类型别名
type Search string

// 接受一个字符串并返回 Search 类型
func NewSearch(s string) Search {
   return Search(s)
}

// 这里出现了一些奇怪的情况
// 为了进行任意测试,返回一个整数
func PrintSearch(s Search) int {
    return 5
}

我的假设是,如果我使用 NewSearch 创建一个对象,我应该能够将其传递给 PrintSearch 并且一切都按预期运行,但如果我将一个原始字符串传递给 PrintSearch,它不应该编译通过。但是,我没有遇到这种行为。

主要代码:

package main

import (
    "fmt"
    ".../search" // 这里不需要输入完整的路径
)

func main() {
   SearchTerm := search.NewSearch("Test")
   StringTerm := "Another test"

   fmt.Println(search.PrintSearch(SearchTerm)) // 这应该打印出 5
   fmt.Println(search.PrintSearch(StringTerm)) // 这应该引发编译错误,但实际上没有
}

似乎如果我将类型和函数写在与 main 相同的包中,一切都按照我预期的方式工作?也就是说,它会引发编译错误。我是否忽略了有关跨包类型转换的某些内容?

英文:

Sorry for the ambiguous title. I'm not getting a compiler error when I believe that I should, based on creating a new type and a function that takes an argument of that type.

The example:

package search

//Some random type alias
type Search string

//Takes a string and returns Search
func NewSearch(s string) Search {
   return Search(s)
}

//This is where things are getting weird
//Returns an int just for arbitrary testing
func PrintSearch(s Search) int{
    return 5
}

Now my assumption would be, if I created an object using NewSearch, I would be able to pass it to PrintSearch and have everything run as expected, but if I passed PrintSearch a primitive string, it should not compile. I am not experiencing this behavior.

The main code:

package main
import (
    "fmt"
    ".../search" //no need to type the whole path here
)

func main() {
   SearchTerm := search.NewSearch("Test")
   StringTerm := "Another test"

   fmt.Println(search.PrintSearch(SearchTerm)) // This should print 5
   fmt.Println(search.PrintSearch(StringTerm)) // This should throw a compiler error, but it is not
}

It seems like if I write the type and the function in the same package as main, everything works as I'd expect? As in, it throws a compiler error. Is there something I've missed about cross-package type coercion?

答案1

得分: 1

我们可以进一步简化这个例子(playground):

package main

type Foo string

type Bar int

func main() {
    var f Foo = "foo"
    var b Bar = 1
    
    println(f, b)
}

这在规范的可赋值性部分中有解释。

值x在以下任何情况下都可以赋值给类型为T的变量("x可以赋值给T"):

  • x的类型与T相同。
  • x的类型V和T具有相同的基础类型,并且V或T中至少有一个不是命名类型。
  • T是接口类型,并且x实现了T。
  • x是双向通道值,T是通道类型,x的类型V和T具有相同的元素类型,并且V或T中至少有一个不是命名类型。
  • x是预声明的标识符nil,T是指针、函数、切片、映射、通道或接口类型。
  • x是可由类型T的值表示的无类型常量。
英文:

We can simplify this example a bit further (playground):

package main

type Foo string

type Bar int

func main() {
    var f Foo = "foo"
    var b Bar = 1
    
    println(f, b)
}

This is explained in the spec's assignability section.

> A value x is assignable to a variable of type T ("x is assignable to
> T") in any of these cases:
>
> * x's type is identical to T.
> * x's type V and T have identical underlying types and at least one of V or T is not a named type.
> * T is an interface type and x implements T.
> * x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type.
> * x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
> * x is an untyped constant representable by a value of type T.

huangapple
  • 本文由 发表于 2016年9月27日 10:07:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/39714950.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定