Я использую пользовательские типы, и у меня есть проблема, когда задействованы указатели, как показано ниже.
Код ниже действителен:
package main
import (
"fmt"
)
type deck []string
func newDeck(cards ...string) deck {
return cards
}
Код ниже также действителен:
package main
func str(n []string) *[]string {
return &n
}
Вместо этого приведенный ниже код недействителен. Почему так? Мне нужно написать преобразование типа, например return (*deck)(&cards)
package main
import (
"fmt"
)
type deck []string
func newDeck(cards ...string) *deck {
return &cards // compiles with return (*deck)(&cards)
}
Итак, вы говорите, что []string
и deck
не являются разными типами, а *[]string
и *deck
являются?
Несмотря на то, что они имеют один и тот же базовый тип, []string
и deck
являются разными типами; следовательно, таковы *[]string
и *deck
.
Итак, почему первый пример работает, потому что cards
является типом []string
, и я возвращаю deck
. go.dev/play/p/y_oVb57CO5h
ответ blackgreen проясняет это (он меня опередил!)
Правила присвоений (включая возвраты) определены в Спецификации Go: назначаемость. Тот, который имеет отношение к вашему делу:
V
andT
have identical underlying types and at least one of V or T is not a named type.
И Базовые типы:
If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself.
Первый пример компилируется, потому что []string
— литерал безымянного типа с базовым типом []string
(сам), а deck
— именованный тип с базовым типом []string
(согласно вашему определению типа).
Второй пример не компилируется, потому что и *[]string
, и *deck
являются литералами безымянных типов, которые сами по себе являются (разными) базовыми типами.
Чтобы второй пример скомпилировался, можно не полагаться на прямое присваивание, а, как вы выяснили, использовать явное преобразование типов
return (*deck)(&cards)
И это преобразование действительно из-за следующего правило:
ignoring struct tags (see below),
x
's type andT
are pointer types that are not named types, and their pointer base types are not type parameters but have identical underlying types.
Спасибо за разъяснение, что *[]string
и *deck
имеют разные базовые типы (хотя []string
и deck
имеют один и тот же базовый тип). Это то, чего мне не хватало, и я не мог найти в спецификации.
*[]string
и*deck
равны различные типы. Вы должны преобразовать первое во второе перед возвратом:return (*deck)(&cards)
. См. go.dev/play/p/HexSf4__9V5