HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

Go言語のパッケージ名と変数名の罠

Go言語で以下のようなコードを書いて一瞬ハマったのでメモ。

package main

import (
    "fmt"
    "container/list"
)

func main() {
    list := list.New()
    list.PushBack(1)
    list.PushBack(2)
    list.PushBack(3)
    for elem := list.Front(); elem != nil; elem = elem.Next() {
        fmt.Println(elem.Value)
    }

    list2 := list.New()
    list2.PushBackList(list)
    for elem := list2.Front(); elem != nil; elem = elem.Next() {
        fmt.Println(elem.Value)
    }
}
$ go run Main.go
# command-line-arguments
./Main.go:17: list.New undefined (type *list.List has no field or method New)
$ 

‥えっ?

17行目は以下の部分。

    list2 := list.New()

実はこれ、9行目の

    list := list.New()

listという名前の変数を定義することによって、パッケージ名よりも変数名の方が優先されてしまうことが原因(多分)。

なので、以下のようにでも書いてやり、パッケージ名と変数名の衝突を避けてやらないといけない。

package main

import (
    "fmt"
    "container/list"
)

func main() {
    aList := list.New()
    aList.PushBack(1)
    aList.PushBack(2)
    aList.PushBack(3)
    for elem := aList.Front(); elem != nil; elem = elem.Next() {
        fmt.Println(elem.Value)
    }

    aList2 := list.New()
    aList2.PushBackList(aList)
    for elem := aList2.Front(); elem != nil; elem = elem.Next() {
        fmt.Println(elem.Value)
    }
}

Javaだったら、以下のようなコードが許されるんだがな(良い悪いは別として)。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> List = new ArrayList<>();
        List.add(1);
        List.add(2);
        List.add(3);
        for (Integer elem : List) {
            System.out.println(elem);
        }

        List<Integer> List2 = new ArrayList<>();
        List2.addAll(List);
        for (Integer elem : List2) {
            System.out.println(elem);
        }
    }
}