ホームページ >バックエンド開発 >Golang >Golang で列挙を実装する方法の簡単な分析 (コード付き)

Golang で列挙を実装する方法の簡単な分析 (コード付き)

青灯夜游
青灯夜游転載
2022-02-04 09:00:315518ブラウズ

Golang で列挙を実装するにはどうすればよいですか? Golangで列挙型を実装する方法については、次の記事で紹介しますので、ご参考になれば幸いです。

Golang で列挙を実装する方法の簡単な分析 (コード付き)

プログラミングの分野では、列挙型は限られた数の固定値のみを含む型を表すために使用され、通常は開発中のエラー コードやステート マシンを識別するために使用されます。 。エンティティ オブジェクトのステート マシンを例にとると、これは通常、データベース内のこのオブジェクトの対応するレコードの状態を識別するフィールド値に対応します。 [関連する推奨事項: Go ビデオ チュートリアル ]

プログラミングを初めて学習し始めたとき、マジック ナンバーを直接使用して判断を行うコードを書いたか、少なくとも見たことがあるはずです。マジック ナンバーとは何ですか? たとえば、記事をトップに固定したい場合は、まずその記事が公開されているかどうかを判断する必要があります。

if (article.state == 2) {
   // state 2 代表文章已发布
}

コードにコメントがない場合、またはプロジェクトのコードがこれらのマジックナンバー判定で埋め尽くされている場合、頭が痛くなりませんか?

その後、これらのステータス値を定数として定義する方法を学び、このロジックを個別にカプセル化するオブジェクトのステータスを決定するメソッドも開発しました。

public class ArticleState {
    
    public static final int Draft = 1; //草稿
    
    public static final int Published = 2; //发布
    
    public static final int Deleted = 3; // 已删除
}

public  Boolean checkArticleState(int state) {
    
    ...
    
}

この使用法は、プログラム内で判断を下すためにマジック ナンバーを直接使用するよりもはるかに優れています。少なくとも、頭が痛くなったり、悪態をつきたくなるようなことはありません。

しかし、後で私を連れて行ってくれた兄貴は、このメソッドにも欠点があると言いました。上記の checkArticleState メソッドは、記事のステータスを確認するために使用されます。呼び出し元に 3 つの静的メソッドのいずれかを渡すことを目的としています。 ArticleState の定数ですが、Type 制約がないため、任意の int 値を渡すことが構文的に許可され、コンパイラは警告を発行しません。列挙型を使用する方が適切です。

em~! 大学で Java を教えていた学期中に先生がこのことについて話していたことを覚えていません。これは、授業中に携帯電話で遊んでいるときに見逃した別の知識ポイントでしょうか?したがって、列挙型を使用した後の Java コードは次のようになります。

// 使用enum而非class声明
public enum ArticleState {
	
    //要在enum里创建所有的枚举对象
    Draft(1, "草稿");
    Published(2, "已发布");
    Deleted(3, "已删除")
      
    // 自定义属性
    private int code;

    private String text;
  
    // 构造方法必须是private的
    ArticleState(int code, String text) {
        this.code = id;
        this.text = name;
    }
}

public  Boolean checkArticleState(ArticleState state) {
    
    ...
    
}

これにより、仮パラメータの列挙型を使用して不正な状態値を除外し、その整数値をパラメータとして checkArticleState に渡すことができます。型の不一致はコンパイルできないため、コンパイラはコードを作成するときにすぐに要求することができます。

これまで Java を使用したことがない場合でも、心配しないでください。主要な文法上のポイントをコメントでマークしましたので、誰でも理解できるはずです。

過去 2 年間、私は主に Go を使用してプロジェクトを実行していましたが、Go にも同様の問題が存在することがわかりましたが、Go には列挙型が用意されていませんでした。では、ステータス値を正しく制限するにはどうすればよいでしょうか? int 型定数を使用したままでは、間違いなく機能しません。例:

 const (
     Draft int = 1
     Published = 2
     Deleted   = 3
 )

 const (
     Summer int = 1
     Autumn     = 2
     Winter     = 3
     Spring     = 4
 )

 func main() {
     // 输出 true, 不会有任何编译错误
     fmt.Println(Autumn == Draft)
 }

たとえば、上記では 2 セットの int 型定数が定義されており、1 つは記事のステータスを表し、もう 1 つは四季を表しています。この方法で記事のステータスとシーズンを比較するときにコンパイル エラーが発生することはありません。

答えは、Go の組み込みライブラリ、または誰もが知っているいくつかのオープン ソース ライブラリのコードの中に見つかります。たとえば、gRPC エラー コードが google.golang.org/grpc/codes でどのように定義されているかを見ると、列挙を正しく実装する方法を理解できます。

基本型として int を使用してエイリアス型を作成できます。Go はこれをサポートしています。

type Season int

const (
	Summer Season = 1
	Autumn        = 2
	Winter        = 3
	Spring        = 4
)

もちろん、連続定数値を定義する場合、Go では iota がよく使用されるため、上記定義はまだ有効ですが、さらに簡略化することができます。

type Season int

const (
	Summer Season = iota + 1
	Autumn
	Winter
	Spring
)

type ArticleState int

const (
  Draft int = iota + 1
  Published
  Deleted  
)

func checkArticleState(state ArticleState) bool {
	// ... 
}

 func main() {
   // 两个操作数类型不匹配,编译错误
   fmt.Println(Autumn == Draft)
	// 参数类型不匹配,但是因为 ArticleState 底层的类型是 int 所以传递 int 的时候会发生隐式类型转换,所以不会报错
   checkArticleState(100)
 }

これらのステータス値の基になる型はすべて int 値ですが、現在はあらゆる場所でステータス値を使用しているため、2 つの無関係な型の列挙値を比較するとコンパイル エラーが発生します。

ただし、ArticleState の基になる型は int であるため、関数 checkArticleState のパラメーターの型は ArticleState に設定されます。したがって、checkArticleState を呼び出すときに、int 型パラメータを渡すと、暗黙的な型変換が発生し、コンパイル エラーは発生しません。この問題を解決したい場合は、型を再定義するだけで解決できます。 StackOverflow この回答を参照できます:

https://stackoverflow.com/questions/50826100/how-to-disable-implicit-type-conversion-for-constants

続きプログラミング関連の知識については、

プログラミング ビデオ
をご覧ください。 !

以上がGolang で列挙を実装する方法の簡単な分析 (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。