はじめに
直近はRUSTを勉強していますが、以前勉強したGolangを忘れないように、Tour of Go を利用して復習します。interfaceの理解に対して、忘れないようにここでメモを残ります。
Key: Struct, pointer, interface
Target
part1: インタフェースでポインターを出力できるようにする
part2: インタフェースが出力タイプを指定する際に、ポインター指定クラスが利用して、errorの再定義ができる
コード試す
part1
main.go
package main
import "fmt"
// インタフェース
type I interface {
M()
}
// 構造体
type mystring struct {
S string
}
// mystringのポインタクラス
func (f *mystring) M() {
if f == nil {
fmt.Println("<nil>")
return
}
fmt.Println("print S value {}", f.S)
}
// メインメソッド
func main() {
var i I
var t *mystring
i = t
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("describe the result (%v, %T)\n", i, i)
}
出力結果:
bash.sh
describe the result (<nil>, *main.mystring)
<nil>
ここから見ると、構造体のポインターを「t」定義して、インタフェース「i」を渡して、出力をすることができました。
main.go
package main
import "fmt"
// インタフェース
type I interface {
M()
}
// 構造体
type mystring struct {
S string
}
// mystringのポインタクラス
func (f *mystring) M() {
if f == nil {
fmt.Println("<nil>")
return
}
fmt.Printf("print S value is %v ,pointer is %v", f.S, &f.S)
}
// メインメソッド
func main() {
var i I
var middlestring = mystring{"Mike"}
i = &middlestring
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("describe the result (%v, %T)\n", i, i)
}
出力結果
bash.sh
describe the result (&{Mike}, *main.mystring)
print S value is Mike ,pointer is 0xc000108050
ポインターを出力できました。
part2
main.go
package main
import (
"fmt"
"time"
)
type error interface {
Error() string
}
type error2 interface {
Error2() string
}
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error2() string {
return fmt.Sprintf("at222 %v, %s",
e.When, e.What)
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run2() error2 {
return &MyError{
time.Now(),
"it didn't works",
}
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
if err2 := run2(); err2 != nil {
fmt.Println(err2)
}
}
出力結果
bash.sh
at 2009-11-10 23:00:00 +0000 UTC m=+0.000000001, it didn't work
at 2009-11-10 23:00:00 +0000 UTC m=+0.000000001, it didn't works <- ※※おかしい
結果からみると、run2()の返す結果は「Error()」クラスになっています。謎だ。。
error はデフォルトインタフェースのことでしょう?
main.go
package main
import (
"fmt"
"time"
)
type error interface {
Error() string
}
type error2 interface {
Error2() string
}
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error2() string {
return fmt.Sprintf("at222 %v, %s",
e.When, e.What)
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run2() interface{} {
return func() interface{} {
var Error2 error2
Error2 = &MyError{time.Now(), "it didn't works"}
return Error2.Error2()
}() # <-- ここは「()」を使用しないとポインターを返す
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
if err2 := run2(); err2 != nil {
fmt.Println(err2)
}
}
出力結果
bash.sh
at 2009-11-10 23:00:00 +0000 UTC m=+0.000000001, it didn't work
at222 2009-11-10 23:00:00 +0000 UTC m=+0.000000001, it didn't works
結局、原因がわからないですが、一応、run2()の返す結果はinterfaceを定義し、error2 interfaceを再導入し、返す方針にして、解決できました。
まとめ
- 既存なデフォルトインタフェースをしておくべきかな。