質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

1回答

1132閲覧

メソッド内で引数の型に応じたスライスを作りたい

tenpu

総合スコア40

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2022/09/01 16:25

編集2022/09/02 01:31

前提

Goについて質問です。
とある自作パッケージAに引数(any)付きのメソッド"hoge"があります。
そのメソッドは別パッケージBから呼んでいます。引数には、ケースに応じて複数種のユーザ定義型(仮に)のいずれかのインスタンス変数をセットしています。引数の型がanyのため、事前の型指定はできません。

実現したいこと

メソッドA内で、呼び元が渡した引数の型(ユーザ定義型)でsliceを作成したいのですが、良い方法はありますでしょうか?

それをメソッドの戻り値にしたいです。

ここに実現したいことを箇条書きで書いてください。

  • 引数(任意のユーザ定義型)に応じた型のsliceをメソッド内で作成したい。

 (このsliceを戻り値にするので、sliceの型が、[]UserDefinedStruct1 またはinterface{} | []UserDefinedStruct1(→[]anyの変数に []UserDefinedStruct1をappendした場合にデバッグ表示される型))
メソッドの戻り値がanyなので、sliceの型はどちらでも変わらない。

発生している問題・エラーメッセージ

---

該当のソースコード

Goになります。

package(A)

1 2(略) 3func New () { 4 return 5} 6 7func (<レシーバー>) Hoge (argData any) any { 8 9}

package(B)

1 2(略) 3 4func (<レシーバー>) Fuga (argData any) any { 5 6aaa := A.New() 7data := aaa.Hoge(C.UserDefinedStruct1{}) 8 9// dataを使った処理 10... 11 12}

package(C)

1 2// 独自のstructを定義 3type UserDefinedStruct1 struct { 4 xxx int 5 ... 6} 7 8type UserDefinedStruct2 struct { 9 yyy int 10 ... 11} 12 13type UserDefinedStruct3 struct { 14 zzz int 15 ... 16} 17 18... 19

試したこと

現状は、やり方が見つかっていないため下記のようになってしまいます。メソッドのため、型パラメータは使えず。

package(A)

1 2func (<レシーバー>) Hoge (argData any) any { 3 4 var sliceSample []any 5 6 for ... { 7 8 (json読み込み処理unmarshalで、argDataに都度セット) 9   10 sliceSample = append(sliceSample, argData) 11 12 } 13 14 return sliceSample // この戻り値型は interface{} | map[string]interface{} → 例. interface{} | UserDefinedStruct1 のようにしたい 15}

引数[]anyを追加して外から渡そうとしましたが、[]anyにはany以外の型で構成されるスライス(例.[]string)はセットできないのでダメでした。

Hoge (argData any, sliceParam []any) // []anyは他の型のスライス渡しができないので、却下

また、anyの引数を追加してそこに[]UserDefinedStruct1をセットする方法も試しましたが、追加引数が型[]Typeとして使用できないためエラーでした。

Hoge (argData any, sliceParam any) { sliceParam = append(sliceParam, argData) // そもそもsliceSampleを[]Typeとして使用できずエラー }

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

案のひとつは「メソッドをやめて関数で実装する」です。事例を見る限りメソッドである必要性がないように見受けられますので。

「(例: sliceの型が、[]UserDefinedStruct1 またはinterface{} | []UserDefinedStruct1 )」という説明がちょっとわかりにくいです。「any または []UserDefinedStruct1」を返値とするのでしょうか?anyが必要な理由はありますか?

GoとGenericsについて補足

  • 抽象データ型以外でのGenericsのご利用は控えめに。以下理由。
  • When To Use GenericsHashiCorp.の中の人のツイート を参考に。
  • 実はGo1.18以前のinterfaceイディオムだけで済む場合が往々にしてある。
  • なにをスライスとして保持したいのかをもっと具体的に掘り下げてみるとよいかも。
  • どんなデータ型が来てもOKにするというのは型安全を捨てるのと同義です。

投稿2022/09/01 23:34

編集2022/09/02 03:17
nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tenpu

2022/09/02 01:33

ご提案ありがとうございます。 関数での実装も検討してみます。本件とは別に複数のリポジトリが既にありまして、それらと構成を統一するためにメソッドを使っています。(interfaceのみのパッケージ(そこでメソッドのみ定義)を挟んでおります) sliceの型については、分かりづらいと思いますので「実現したいこと」の説明に追記しました。伝わりますでしょうか?
nobonobo

2022/09/02 02:56

interface{} | []UserDefinedStruct1の「|」はデバッグ表示されていますか?「デバッグ表示」とは具体的に何を行った表示ですか?
nobonobo

2022/09/02 03:23

先に「具体的な型を列挙し、それらの共通した操作や振る舞い」を明確にするとよいかも。 そしてまずは適切な共通した操作や振る舞いを持つインターフェースを設けるやり方で済まないかを検討しましょう。それでもなお汎用の型を扱えるようにすることが重要であれば、ここではじめてGenericsを検討してください。
tenpu

2022/09/09 01:40

> 「デバッグ表示」とは具体的に何を行った表示ですか? デバッガでブレイクポイントで止めた際に確認した内容になります。 型違いの共通処理を何度か行う必要があるので汎用型を行いたく検討していましたが、メソッドをやめて関数にする方針にしようと思います。→Generics対応ができる。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問