0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Golangのinterfaceでポインターを試した

Last updated at Posted at 2022-09-11

はじめに

直近は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を再導入し、返す方針にして、解決できました。

まとめ

  • 既存なデフォルトインタフェースをしておくべきかな。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?