Как я могу создать собственный тип в Go, который ограничен определенным списком строковых значений? например
type Suit = "Spade" | "Diamond" | "Club" | "Heart"
В Go нет алгебраических типов данных (ADT). То, что вам нужно, это тип «сумма» в ADT. Например, в Swift и Rust есть перечисления для их поддержки. Go не имеет дженериков (пока); Варианта нет, Тип результата тоже.
В то время как то, что вы хотите сделать, может быть достигнуто различными способами в Go, мне нравится использовать const вместо пустого интерфейса или проверки типа или отражения. Я думаю, что const будет более быстрым и читаемым. Вот как я пойду. Вы можете вернуть строку из метода вместо печати, если это то, что вы хотите.
package main
import "fmt"
type Suit int
const (
Spade Suit = iota + 1
Diamond
Club
Heart
)
type Card struct {
suit Suit
no int
}
func (c *Card) PrintSuit() {
switch c.suit {
case Spade:
fmt.Println("Its a Spade")
case Diamond:
fmt.Println("Its a Diamond")
case Club:
fmt.Println("Its a Club")
case Heart:
fmt.Println("Its a Heart")
default:
fmt.Println("Unknown!")
}
}
func main() {
c := Card{suit: Diamond}
c.PrintSuit()
}
Вы можете принять внешнюю функцию в таких методах, как PrintSuit
, если логика обработки является внешней.
Нежелательные значения обрабатываются в условиях переключения. Важно то, что костюм начинается с iota + 1
, а не просто с йоты, так как я хочу избежать присвоения значения 0 любому типу костюма, потому что это случай по умолчанию, когда кто-то делает Card{}
. Также вам нужно позаботиться о правильной инициализации в функции NewCard, которая создает правильную карту {}.
This route doesn't do anything to prevent a Suit
вы можете рассмотреть возможность использования неэкспортируемого типа только с экспортируемыми значениями.
Определите псевдоним типа для string
, то есть Suit
. Suit
— это тип, базовым типом которого является строка.
Теперь создайте константы типа Suit. В следующей оде Spade
, Diamond
, Club
, Heart
относятся к типу Suit. Теперь функция, в которой вы хотите, чтобы параметр был ограничен некоторым вводом (что невозможно); но что вы можете сделать, чтобы ограничить его принятие только типа Suit
и передать любую из созданных переменных const
.
// Define new type alias for string
type Suit string
const (
Spade Suit = "Spade"
Diamond Suit = "Diamond"
Club Suit = "Club"
Heart Suit = "Heart"
)
// function f only accepts parameter of type "Suit"
func f(s Suit) {
fmt.Println(s)
}
func main() {
// Call the function f with Spade
f(Spade)
}
это не то, как вы создаете типы данных с ограниченными значениями, а также, как сказал @Abhijit_K, go не поддерживает это.
this (type Suit string
) не является псевдонимом типа, псевдоним типа имеет определенный синтаксис с определенным поведением. Это обычное объявление типа golang.org/ref/spec#Type_declarations
@whitespace В ответе уже написано, что это на самом деле невозможно.
Суть в том, чтобы иметь поддержку редактора, и это просто позволяет мне вводить что угодно в функцию. Я бы не рекомендовал это.
Этот маршрут ничего не делает для предотвращения присвоения значению
Suit
нежелательного значения (например,suit = Suit(123)
), но, возможно, это наиболее подходящее решение для такого случая использования.