Назначение Go с использованием указателей на пользовательские типы

Я использую пользовательские типы, и у меня есть проблема, когда задействованы указатели, как показано ниже.

Код ниже действителен:

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 равны различные типы. Вы должны преобразовать первое во второе перед возвратом: return (*deck)(&cards). См. go.dev/play/p/HexSf4__9V5
jub0bs 09.04.2022 15:03

Итак, вы говорите, что []string и deck не являются разными типами, а *[]string и *deck являются?

Halil Yıldırım 09.04.2022 15:09

Несмотря на то, что они имеют один и тот же базовый тип, []string и deck являются разными типами; следовательно, таковы *[]string и *deck.

jub0bs 09.04.2022 15:09

Итак, почему первый пример работает, потому что cards является типом []string, и я возвращаю deck. go.dev/play/p/y_oVb57CO5h

Halil Yıldırım 09.04.2022 15:13

ответ blackgreen проясняет это (он меня опередил!)

jub0bs 09.04.2022 15:38
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
2
5
36
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Правила присвоений (включая возвраты) определены в Спецификации Go: назначаемость. Тот, который имеет отношение к вашему делу:

V and T 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 and T 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 имеют один и тот же базовый тип). Это то, чего мне не хватало, и я не мог найти в спецификации.

jub0bs 09.04.2022 15:37

Другие вопросы по теме