daily pastebin goal
90%
SHARE
TWEET

Untitled

a guest Mar 21st, 2019 37 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package main
  2.  
  3. import (
  4.   "fmt"
  5.   "reflect"
  6.   "testing"
  7. )
  8.  
  9. type NotPointerError struct {
  10.   msg string
  11. }
  12.  
  13. func (err *NotPointerError) Error() string {
  14.   return err.msg
  15. }
  16.  
  17. type AssignableError struct {
  18.   msg string
  19. }
  20.  
  21. func (err *AssignableError) Error() string {
  22.   return err.msg
  23. }
  24.  
  25. // ポインタpの指す先にvの値を入れる関数。
  26. // 不適切な値があったらエラーを返す。
  27. // 変更するのはSetの内部だけ。
  28. func Set(p, v interface{}) error {
  29.   pv := reflect.ValueOf(p)
  30.   // pがポインタかどうかKindをチェック
  31.   if pv.Kind() != reflect.Ptr {
  32.     return &NotPointerError{"pがポインタじゃないよん"}
  33.   }
  34.  
  35.   vv := reflect.ValueOf(v)
  36.   // pに値がセットできるかつ、pの先にvが代入できるかチェック
  37.   if !pv.Elem().CanSet() || !vv.Type().AssignableTo(pv.Elem().Type()) {
  38.     return &AssignableError{"pに値がセットできないよん"}
  39.   }
  40.  
  41.   // Elemでポインタの指してる先を取得して代入
  42.   pv.Elem().Set(vv)
  43.   return nil
  44.  
  45. }
  46.  
  47. type myint int
  48.  
  49. func (n myint) String() string {
  50.   return fmt.Sprint(int(n))
  51. }
  52.  
  53. func TestSet(t *testing.T) {
  54.   var (
  55.     v1 int
  56.     v2 fmt.Stringer
  57.   )
  58.  
  59.   cases := map[string]struct {
  60.     p, v      interface{}
  61.     expectErr bool
  62.   }{
  63.     "ok":       {&v1, 100, false},
  64.     "stringer": {&v2, myint(100), false},
  65.     "myint":    {&v1, myint(100), true},
  66.     "nil":      {nil, 100, true},
  67.     "string":   {&v1, "hoge", true},
  68.     "float64":  {&v1, 1.11, true},
  69.     "func":     {&v1, func() {}, true},
  70.   }
  71.  
  72.   for tn, tc := range cases {
  73.     tc := tc
  74.     t.Run(tn, func(t *testing.T) {
  75.       defer func() {
  76.         if r := recover(); r != nil {
  77.           t.Fatal("panicが起きた:", r)
  78.         }
  79.       }()
  80.  
  81.       err := Set(tc.p, tc.v)
  82.       switch {
  83.       case tc.expectErr && err == nil:
  84.         t.Fatal("期待したエラーが発生しませんでした")
  85.       case !tc.expectErr && err != nil:
  86.         t.Fatal("予想外のエラー:", err)
  87.       case err == nil:
  88.         v := reflect.ValueOf(tc.p).Elem().Interface()
  89.         if !reflect.DeepEqual(v, tc.v) {
  90.           t.Errorf("want %v but got %v", tc.v, v)
  91.         }
  92.       }
  93.     })
  94.   }
  95. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top