SSブログ

Golangでファイルポインタを関数の引数で渡せなかった。(解決した) [プログラミング]

何か腑に落ちないGolangの仕様みたいなんだけど、ファイルを開いてからその先の別の関数の中で書いたり読んだりできないみたいなのだ。そもそもファイルポインタが引数として渡せない仕様になっていて、コンパイルが通らなかったり実行ができない。もしかしたらすごい初歩的なところでつまづいているのかもしれないですが、できないものはできないので書いておく。

実際のソースを見ていこうと思う。まずは動くソースを示します。何か別の問題があると話が止まっちゃうしね。とりあえずos.Create()で開いて、WriteString()で書いてみます。

package main

import "os"

func main() {
	fp, err := os.Create("hoge.txt")
	if err != nil {
		panic(err)
	}
	fp.WriteString("てすとだよ?ん\n")
}


ふむ、普通にファイルができて書き込めている。これを関数に書き出して、ファイルポインタを渡してみようと思う。

これだとエラーが出て実行できない。
package main

import "os"

func main() {
	fp, err := os.Create("hoge.txt")
	if err != nil {
		panic(err)
	}
	foo(fp)
}

func foo(fp *File) {
	fp.WriteString("てすとだよ?ん\n")
}


エラー表示は以下で、
$ go run sample.go 
# command-line-arguments
./sample.go:13:13: undefined: File


Create()で*File型のファイルポインタができているはずなんだけど、引数に指定できない。型は間違っていないはず。
https://pkg.go.dev/os#Create
でもFile型が定義されていないと出る。意味不明。
*をつけたりつけなかったりしてもダメでした。


今度はbufioを使ってみる。
package main

import (
	"bufio"
	"os"
)

func main() {
	fp, err := os.Create("hoge.txt")
	if err != nil {
		panic(err)
	}
	writer := bufio.NewWriter(fp)
	_, err = writer.WriteString("てすとだす\n")
	if err != nil {
		panic(err)
	}
	writer.Flush()
}

普通にファイルに書き出される。でも、ファイルポインタと同様に、writerを渡して関数に外出しにしようとすると同様に実行できなかったり、コンパイラに嫌われる。

package main

import (
	"bufio"
	"os"
)

func main() {
	fp, err := os.Create("hoge.txt")
	if err != nil {
		panic(err)
	}
	writer := bufio.NewWriter(fp)
	foo(writer)
}

func foo(writer *Writer) {
	_, err := writer.WriteString("てすとだす\n")
	if err != nil {
		panic(err)
	}
	writer.Flush()
}

型もあっているはずなのに、
https://pkg.go.dev/bufio#NewWriter
./sample.go:17:18: undefined: Writer

とFileと同様にダメ扱いされてしまう。どういうことだ。

とりあえずos.Create()などで作った場所で書き込みましょうということらしい。C言語でこういうようなことあったっけ?

とりあえず、関数に引数で渡せないのでどうしようもない。どういう理屈で出来ないのかがわからないのだけれど、大人しくファイルを開いたところで書き込んだりしとけということなんだろうな。何か、腑に落ちない感じ。理由があれば全然いいんだけど、言語的に出来なくしている訳が知りたい。

書き込むデータは別の関数とかで作って、ファイル開いたところに戻せよってことなんだろうけど、やっぱちょっと気持ち悪い。



《後記》

nobonoboさんに指摘していただき、型にパッケージ名が足りていないとわかりました。
具体的には*Fileを*os.Fileとし、*Writerを*bufio.Writerにするというものでした。確かにスコープ的にパッケージ名がないとどこのFileだかWriterだかわかりませんものね。やっぱり初歩的なつまづきでした。サンプルファイルを上げておきます。

package main

import "os"

func main() {
	fp, err := os.Create("hoge.txt")
	if err != nil {
		panic(err)
	}
	foo(fp)
}

func foo(fp *os.File) {
	fp.WriteString("てすとだよ?ん\n")
}


package main

import (
	"bufio"
	"os"
)

func main() {
	fp, err := os.Create("hoge.txt")
	if err != nil {
		panic(err)
	}
	writer := bufio.NewWriter(fp)
	foo(writer)
}

func foo(writer *bufio.Writer) {
	_, err := writer.WriteString("てすとだす\n")
	if err != nil {
		panic(err)
	}
	writer.Flush()
}


タグ:Golang
コメント(0) 
共通テーマ:パソコン・インターネット

コメント 0