<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Go アーカイブ - Sheltie Garage Tech</title>
	<atom:link href="https://sheltie-garage.xyz/tech/category/go/feed/" rel="self" type="application/rss+xml" />
	<link>https://sheltie-garage.xyz/tech/category/go/</link>
	<description>テクノロジー関連の話題をまとめたブログです</description>
	<lastBuildDate>Sun, 18 Jan 2026 12:06:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Go言語の単体テスト入門</title>
		<link>https://sheltie-garage.xyz/tech/2026/01/go%e8%a8%80%e8%aa%9e%e3%81%ae%e5%8d%98%e4%bd%93%e3%83%86%e3%82%b9%e3%83%88%e5%85%a5%e9%96%80/</link>
					<comments>https://sheltie-garage.xyz/tech/2026/01/go%e8%a8%80%e8%aa%9e%e3%81%ae%e5%8d%98%e4%bd%93%e3%83%86%e3%82%b9%e3%83%88%e5%85%a5%e9%96%80/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 18 Jan 2026 12:02:17 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=1323</guid>

					<description><![CDATA[<p>最近はバイブコーディングばっかり行っていて、中身の理解が進まないまま、でもテストでは動作に問題ないプログラムが出来上がっております。(個人開発) 本当にこれでいいのかという思いもあるため、最近は・AIにコードを作ってもら [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2026/01/go%e8%a8%80%e8%aa%9e%e3%81%ae%e5%8d%98%e4%bd%93%e3%83%86%e3%82%b9%e3%83%88%e5%85%a5%e9%96%80/">Go言語の単体テスト入門</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>最近はバイブコーディングばっかり行っていて、中身の理解が進まないまま、でもテストでは動作に問題ないプログラムが出来上がっております。(個人開発)</p>



<p>本当にこれでいいのかという思いもあるため、最近は<br>・AIにコードを作ってもらう<br>・中身をレビューしながら既存コードにマージ<br>みたいなことを行っております</p>



<p>さて、最近作成したプログラムで「単体テストするから、項目を箇条書きで出力して」とAIにお願いしたら、ご丁寧にGoのテストコードが出力された</p>



<p>「そうか、単体テストはもう手動で行う時代では無いのか」と思いつつ、いままでの経験上、ほとんどテストコードを書いたことが無いので、Go言語で単体テストをどうやって記述するのか、改めて学んでみることにした</p>



<h2 class="wp-block-heading">2段階認証の認証コードを生成するロジックを例に、内容を紐解く</h2>



<p>まずはAIが生成したテストコードは以下になります</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>package service

import (
	&quot;testing&quot; // Goの標準テストパッケージ
)

// テスト関数は必ず &quot;Test&quot; で始まる
// 引数は *testing.T を受け取る
func TestGenerateVerificationCode(t *testing.T) {
	// テスト実行
	code, err := GenerateVerificationCode()
	
	// ========================================
	// アサーション（検証）
	// ========================================
	
	// 1. エラーがないことを確認
	if err != nil {
		t.Errorf(&quot;エラーが発生しました: %v&quot;, err)
		return // エラーがあったらここで終了
	}
	
	// 2. コードが6桁であることを確認
	if len(code) != 6 {
		t.Errorf(&quot;コードの長さが不正です。期待値: 6, 実際: %d&quot;, len(code))
	}
	
	// 3. コードが数字のみであることを確認
	for _, char := range code {
		if char &lt; &#39;0&#39; || char &gt; &#39;9&#39; {
			t.Errorf(&quot;数字以外の文字が含まれています: %s&quot;, code)
			break
		}
	}
	
	// ここまで来たらテスト成功！
	t.Logf(&quot;生成されたコード: %s&quot;, code) // ログ出力（-v オプションで表示）
}</code></pre></div>



<h3 class="wp-block-heading">テストコードファイル名</h3>



<p>Goのテストコードはテスト対象のファイル名 + _test.goとなる。大文字小文字の区別あり<br>これは<strong>必須条件</strong>で、Goでは_test.goのファイルを特別に扱う<br>・_test.goは本番バイナリに含まれない<br>・_test.goはgo buildでビルドされない<br>・_test.goはgo testでのみコンパイルされる<br>という特徴がある</p>



<h3 class="wp-block-heading">引数「t *testing.T」について</h3>



<p>tオブジェクトはテスト制御用オブジェクト<br>go testコマンドの実行で自動で設定される</p>



<p>以下のメソッドが呼び出された場合、テストは失敗となる</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>    t.Error(&quot;失敗&quot;)      
    t.Errorf(&quot;失敗&quot;)     
    t.Fatal(&quot;失敗&quot;)      
    t.Fatalf(&quot;失敗&quot;)     
    t.Fail()            
    t.FailNow()         </code></pre></div>



<p>逆にテスト関数が終了するまで上記関数が呼ばれなければ、テストは成功扱い<br>単純に情報を出力するだけであれば、Log(またはLogf)関数を利用する</p>



<h3 class="wp-block-heading">テストの実行方法</h3>



<p>テストの実行にはgo testコマンドを利用する</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>現在のフォルダ配下にあるテストすべてを実行
go test ./...

指定のパッケージのテストを実行
go test ./internal/service/ -v

指定のテストのみ実行
go test ./internal/service/ -v -run TestGenerateVerificationCode</code></pre></div>



<h3 class="wp-block-heading">基本的なアサーション</h3>



<p>基本的にはGo標準のlen関数や&lt;&gt;などの比較演算子を利用してアサーション(検証)を実行する</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>// エラーチェック
if err != nil {
    t.Errorf(&quot;エラーが発生: %v&quot;, err)
}

// 値の比較
if actual != expected {
    t.Errorf(&quot;期待値: %v, 実際: %v&quot;, expected, actual)
}

// 文字列の長さチェック
if len(str) != 6 {
    t.Errorf(&quot;長さが不正: 期待 6, 実際 %d&quot;, len(str))
}

// nilチェック
if value == nil {
    t.Error(&quot;値がnilです&quot;)
}

// 範囲チェック
if count &lt; 0 || count &gt; 100 {
    t.Errorf(&quot;範囲外: %d&quot;, count)
}</code></pre></div>



<p>以上の知識を得たうえで最初のテストコードを眺めてみると、実行していることは至ってシンプルで<br>・認証コード生成関数を実行<br>・実行結果を検証：エラーが発生していないか<br>・実行結果を検証：コードが6桁か<br>・実行結果を検証：すべて数字か<br>の検証を行っているだけの内容となる</p>



<h2 class="wp-block-heading">今後は積極的に使っていきたいテストコード</h2>



<p>以前勤務していた会社ではJava(JTest)を利用して単体テストコードを作成していたけど、モックの使い方などが独特で馴染めなかった記憶があります</p>



<p>Goに関しても、DBやキャッシュと行った部分にはモック的なものを利用する事になりそうですが、それらについては、また次の課題として取り組んでいこうと思います。</p>



<p>GitHubにCIの仕組みが導入されているので、単体テストコードの整備ができればプルリクのたびに自動でテストを実行し、危険なコードはマージを行わないようなワークフローが構築できますね</p>



<p>※記事中のプログラムには生成AIを利用したコードが含まれます</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2026/01/go%e8%a8%80%e8%aa%9e%e3%81%ae%e5%8d%98%e4%bd%93%e3%83%86%e3%82%b9%e3%83%88%e5%85%a5%e9%96%80/">Go言語の単体テスト入門</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2026/01/go%e8%a8%80%e8%aa%9e%e3%81%ae%e5%8d%98%e4%bd%93%e3%83%86%e3%82%b9%e3%83%88%e5%85%a5%e9%96%80/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cookieを消すときはパスに注意</title>
		<link>https://sheltie-garage.xyz/tech/2025/09/cookie%e3%82%92%e6%b6%88%e3%81%99%e3%81%a8%e3%81%8d%e3%81%af%e3%83%91%e3%82%b9%e3%81%ab%e6%b3%a8%e6%84%8f/</link>
					<comments>https://sheltie-garage.xyz/tech/2025/09/cookie%e3%82%92%e6%b6%88%e3%81%99%e3%81%a8%e3%81%8d%e3%81%af%e3%83%91%e3%82%b9%e3%81%ab%e6%b3%a8%e6%84%8f/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 14 Sep 2025 23:15:01 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=1235</guid>

					<description><![CDATA[<p>処理の分岐や、簡易的なトークンの保存などにCookieを利用し、利用が終わったら即座にCookieを消したいと言うことがあると思います。 基本的なCookieの消し方 Cookieの削除方法としては「有効期限を0やマイナ [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2025/09/cookie%e3%82%92%e6%b6%88%e3%81%99%e3%81%a8%e3%81%8d%e3%81%af%e3%83%91%e3%82%b9%e3%81%ab%e6%b3%a8%e6%84%8f/">Cookieを消すときはパスに注意</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>処理の分岐や、簡易的なトークンの保存などにCookieを利用し、利用が終わったら即座にCookieを消したいと言うことがあると思います。</p>



<h1 class="wp-block-heading">基本的なCookieの消し方</h1>



<p>Cookieの削除方法としては「有効期限を0やマイナスに設定」することで削除することができます<br>具体的には、以下のいずれかを行います<br>・Expiresを現在日時より過去を設定する<br>・Max-Ageを0 または マイナスの値を設定する(ただし、マイナスはブラウザにより挙動が変わる可能性があるため、0指定が推奨されているそうです)</p>



<p>自分が開発中のWebアプリでは、以下の方法でCookie削除を行っていました<br>フレームワークとして、Go言語のEchoを利用しています</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>cookie, err := c.Cookie(&quot;token&quot;)
cookie.Expires = time.Now().Add(-1 * time.Hour)</code></pre></div>



<p>ただ、この状態でテストを行ったところ、Cookieがうまく消えていませんでした</p>



<h1 class="wp-block-heading">Cookieが消えない原因</h1>



<p>Cookieが消えなかった原因は2つありました<br>・SetCookieを呼び出していなかった<br>・Cookieのパスを明示的に指定していなかった</p>



<p>SetCookieを呼び出していなかったのは単純なケアレスミスなのですが、Cookieパスについては今回始めて知りました<br>Cookieを削除する際、明示的にpath属性を指定する必要があるようで、削除対象のCookieパスを指定することで正常に削除することができました</p>



<p>修正後のコードは以下のようになります</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>		deleteCookie := &http.Cookie{
			Name:    &quot;token&quot;,
			Value:   &quot;&quot;,
			Expires: time.Unix(0, 0),
			Path:    &quot;/&quot;, // フロントでセットしたPathと合わせる
		}
		c.SetCookie(deleteCookie)</code></pre></div>



<p>Expiresをtime.Unix(0, 0)を利用しているのは、time.Now().Add(-1 * time.Hour)だと何故か過去日付が取得できなかったため、Unix()メソッドを使って確実な過去日時(1970年)を取得しています<br>もちろん、過去日付が設定できればほかメソッドを利用しても大丈夫です</p>



<h1 class="wp-block-heading">まとめ</h1>



<p>ということで、Cookieがうまく消えないというお話でした<br>今回のケースでは<br>・有効期間に過去日時が指定されていなかった<br>・path属性が削除対象のCookieとズレていた<br>というのが原因でした</p>



<p>他にも、DomainやSecure、SameSiteといった属性の違いでも削除されないことがあるため、削除対象のCookieと属性が一致しているか確認するのが重要です<br><br>ので、もしCookie削除が狙ったとおりに動かない場合は、この部分を見直してみると良いかもしれません</p>


<div id="rinkerid1236" class="yyi-rinker-contents  yyi-rinker-postid-1236 yyi-rinker-img-m yyi-rinker-catid-16 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/rakutenkobo-ebooks/cabinet/4125/2000011424125.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">詳解Go言語Webアプリケーション開発【電子書籍】[ 清水陽一郎 ]</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥2,703</span>
															<span class="price_at">(2026/04/19 15:12:45時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=Go%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>


<div id="rinkerid1237" class="yyi-rinker-contents   yyi-rinker-postid-1237 yyi-rinker-no-item">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image"></div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
								【公式】 【SALE40％OFF！】OXO オクソー クッキープレス(ディスクケース付き)【レビューキャンペーン対象】							</div>

			<div class="yyi-rinker-detail">
											</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=Cookie&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FCookie%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DCookie" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
	</div><p>投稿 <a href="https://sheltie-garage.xyz/tech/2025/09/cookie%e3%82%92%e6%b6%88%e3%81%99%e3%81%a8%e3%81%8d%e3%81%af%e3%83%91%e3%82%b9%e3%81%ab%e6%b3%a8%e6%84%8f/">Cookieを消すときはパスに注意</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2025/09/cookie%e3%82%92%e6%b6%88%e3%81%99%e3%81%a8%e3%81%8d%e3%81%af%e3%83%91%e3%82%b9%e3%81%ab%e6%b3%a8%e6%84%8f/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ひとことメモ：gosecで静的にセキュリティスキャンを実行する</title>
		<link>https://sheltie-garage.xyz/tech/2025/07/%e3%81%b2%e3%81%a8%e3%81%93%e3%81%a8%e3%83%a1%e3%83%a2%ef%bc%9agosec%e3%81%a7%e9%9d%99%e7%9a%84%e3%81%ab%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%82%b9%e3%82%ad%e3%83%a3%e3%83%b3/</link>
					<comments>https://sheltie-garage.xyz/tech/2025/07/%e3%81%b2%e3%81%a8%e3%81%93%e3%81%a8%e3%83%a1%e3%83%a2%ef%bc%9agosec%e3%81%a7%e9%9d%99%e7%9a%84%e3%81%ab%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%82%b9%e3%82%ad%e3%83%a3%e3%83%b3/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 13 Jul 2025 12:31:42 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=1197</guid>

					<description><![CDATA[<p>geminiちゃんにgosecというセキュリティチェックツールを教えてもらったのでメモ 概要 goで作成されたプロジェクトに対してセキュリティ診断が行える静的ツールです自分のプロジェクトに対して実施した結果、パスワードの [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2025/07/%e3%81%b2%e3%81%a8%e3%81%93%e3%81%a8%e3%83%a1%e3%83%a2%ef%bc%9agosec%e3%81%a7%e9%9d%99%e7%9a%84%e3%81%ab%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%82%b9%e3%82%ad%e3%83%a3%e3%83%b3/">ひとことメモ：gosecで静的にセキュリティスキャンを実行する</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>geminiちゃんに<a href="https://github.com/securego/gosec">gosec</a>というセキュリティチェックツールを教えてもらったのでメモ</p>



<h2 class="wp-block-heading">概要</h2>



<p>goで作成されたプロジェクトに対してセキュリティ診断が行える静的ツールです<br>自分のプロジェクトに対して実施した結果、パスワードのハードコピーやXSSにつながる記述、適切なエラー処理が組み込まれていない部分などを検出することができました</p>



<h2 class="wp-block-heading">使い方</h2>



<p>自分はローカルインストールの方法で利用しました<br>インストールはgo installでインストールするだけです</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>go install github.com/securego/gosec/v2/cmd/gosec@latest</code></pre></div>



<p>使い方も、goプロジェクトで以下のコマンドを実行するだけ</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>gosec ./...</code></pre></div>



<p>結果が出力されます<br>以下は自分のプロジェクトに実施したときの出力結果の例です</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>G402 (CWE-295): TLS MinVersion too low. (Confidence: HIGH, Severity: HIGH)
    130: 	// TLS設定
  &gt; 131: 	tlsConfig := &tls.Config{
  &gt; 132: 		ServerName: smtpAuthAddress,
  &gt; 133: 	}
    134: 	smtpAuth := smtp.PlainAuth(&quot;&quot;, sender.fromEmailAddress, sender.fromEmailPassword, smtpAuthAddress)</code></pre></div>



<p>出力された結果に沿って修正を行うことで、プロジェクト全体のセキュリティ強度をあげられそうですね</p>



<p>ちなみにgemini cliを使えば、go secのインストールから、指定のプロジェクトのスキャン、結果をまとめて修正方法を決めるまでやってくれるので便利です</p>



<p>go secについてもgeminiと雑談していて教えてもらったので、こういったツールは今後はAI連携が前提となっていきそうですね</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2025/07/%e3%81%b2%e3%81%a8%e3%81%93%e3%81%a8%e3%83%a1%e3%83%a2%ef%bc%9agosec%e3%81%a7%e9%9d%99%e7%9a%84%e3%81%ab%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%82%b9%e3%82%ad%e3%83%a3%e3%83%b3/">ひとことメモ：gosecで静的にセキュリティスキャンを実行する</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2025/07/%e3%81%b2%e3%81%a8%e3%81%93%e3%81%a8%e3%83%a1%e3%83%a2%ef%bc%9agosec%e3%81%a7%e9%9d%99%e7%9a%84%e3%81%ab%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%82%b9%e3%82%ad%e3%83%a3%e3%83%b3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DockerでOpenStack Swiftのローカルテスト環境を作成する</title>
		<link>https://sheltie-garage.xyz/tech/2025/04/docker%e3%81%a7openstack-swift%e3%81%ae%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e3%83%86%e3%82%b9%e3%83%88%e7%92%b0%e5%a2%83%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b/</link>
					<comments>https://sheltie-garage.xyz/tech/2025/04/docker%e3%81%a7openstack-swift%e3%81%ae%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e3%83%86%e3%82%b9%e3%83%88%e7%92%b0%e5%a2%83%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sat, 05 Apr 2025 10:33:15 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[インフラ]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=1158</guid>

					<description><![CDATA[<p>GMO ConoHaのオブジェクトストレージを利用したサービスを開発中ですConoHaはOpenStackで環境が構築されているとのことなので、OpenStack(のオブジェクト管理コンポーネントであるSwift)のテス [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2025/04/docker%e3%81%a7openstack-swift%e3%81%ae%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e3%83%86%e3%82%b9%e3%83%88%e7%92%b0%e5%a2%83%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b/">DockerでOpenStack Swiftのローカルテスト環境を作成する</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>GMO ConoHaのオブジェクトストレージを利用したサービスを開発中です<br>ConoHaはOpenStackで環境が構築されているとのことなので、OpenStack(のオブジェクト管理コンポーネントであるSwift)のテスト環境をローカルマシンに準備することにしました<br>本番環境をテストでも使ってしまうと、必ず事故は起きてしまいますから・・・</p>



<h2 class="wp-block-heading">Docker Composeの準備</h2>



<p>こんな感じのdocker-composeファイルを作成しました</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>services:
  swift:
    image: openstackswift/saio:py3
    container_name: swift
    ports:
      - &quot;8080:8080&quot;  # Swift API を公開
    environment:
      SWIFT_USER: &quot;test:tester&quot;
      SWIFT_KEY: &quot;testing&quot;
      SWIFT_AUTH_URL: &quot;http://localhost:8080/auth/v1.0&quot;
    restart: unless-stopped</code></pre></div>



<p>上記内容でdocker-compose.ymlを作成し、docker composeコマンドで実行すれば環境作成は完了です</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>docker compose up -d</code></pre></div>



<h2 class="wp-block-heading">Tokenを取得</h2>



<p>Swiftにアクセスするためのトークンを取得します<br>以下のコマンドを実行してみてください</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -i -H &quot;X-Auth-User: admin:admin&quot; -H &quot;X-Auth-Key: admin&quot; http://localhost:8080/auth/v1.0</code></pre></div>



<p>以下のレスポンスが返却されます</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6
X-Storage-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6
X-Auth-Token-Expires: 86399
X-Storage-Url: http://localhost:8080/v1/AUTH_admin
Content-Length: 0
X-Trans-Id: txf47d5c5ccaa34211bd616-0067f0f8af
X-Openstack-Request-Id: txf47d5c5ccaa34211bd616-0067f0f8af
Date: Sat, 05 Apr 2025 09:32:31 GMT</code></pre></div>



<p>この中の「X-Auth-Token」控えておきます(このあとのAPI操作に利用します)</p>



<h2 class="wp-block-heading">Storageの基本的な操作</h2>



<p><strong>コンテナ一覧表示</strong><br>※コンテナはファイルを保存するための入れ物のような概念</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -H &quot;X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot; \
  http://localhost:8080/v1/AUTH_admin</code></pre></div>



<p><strong>コンテナ作成</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -X PUT \
  -H &quot;X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot; \
  http://localhost:8080/v1/AUTH_admin/test_container</code></pre></div>



<p>コンテナ作成コマンドを実行したあとにコンテナ一覧のコマンドを実行すると、作成したコンテナが表示されると思います</p>



<p><strong>コンテナ公開設定</strong><br>公開設定を行うことで、誰でもファイルを閲覧できるようになります</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -i -X POST \
  -H &quot;X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot; \
  -H &quot;X-Container-Read: .r:*,.rlistings&quot; \
  http://localhost:8080/v1/AUTH_admin/test_container</code></pre></div>



<p><strong>コンテナ内のファイル一覧表示</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -H &quot;X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot; \
  http://localhost:8080/v1/AUTH_admin/test_container</code></pre></div>



<p><strong>コンテナ内のファイル削除</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>コンテナ内のファイル削除
curl -X DELETE \
  -H &quot;X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot; \
  http://localhost:8080/v1/AUTH_admin/test_container/file.txt</code></pre></div>



<p><strong>コンテナ削除</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -X DELETE \
  -H &quot;X-Auth-Token: AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot; \
  http://localhost:8080/v1/AUTH_admin/test_container</code></pre></div>



<h2 class="wp-block-heading">gophercloudでの利用例</h2>



<p>Swiftの操作にgohpercloudを利用しています<br>gophercloudではtokenを利用した認証には対応していない?(未調査)ようなので、操作に利用するクライアントは手動でtokenを取得して設定します</p>



<p><strong>トークンの取得</strong></p>



<p>gophercloudで利用するためのトークンを取得します<br>先ほど紹介した取得方法と相違ありません</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>curl -i -H &quot;X-Auth-User: admin:admin&quot; -H &quot;X-Auth-Key: admin&quot; http://localhost:8080/auth/v1.0</code></pre></div>



<p>レスポンスヘッダの「X-Auth-Token」「X-Storage-Url」を控えておきます</p>



<p><strong>gophercloudのクライアント作成</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>	token := &quot;AUTH_tk37d434e83e6d4a8d94c9b5079ef96aa6&quot;  // 取得したX-Auth-Tokenの値
	storageURL := &quot;http://localhost:8080/v1/AUTH_admin&quot; // 取得したX-Storage-Urlの値

	// ProviderClient を手動で作成
	provider = &gophercloud.ProviderClient{
		TokenID: token,
	}
	// EndpointLocatorを上書きして、常に取得したストレージURLを返すようにする
	provider.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
		return storageURL, nil
	}

	client, err := openstack.NewObjectStorageV1(provider, gophercloud.EndpointOpts{})
	if err != nil {
		panic(err)
	}</code></pre></div>



<p>これでclientが作成され、以降ストレージを操作するときはclientを利用して操作します</p>



<p><strong>ファイルの作成</strong></p>



<p>ファイルを開いて、アップロードする処理を抜粋しています</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>file, err := os.Open(fileName)
opt := objects.CreateOpts{
	Content: file,
}
result := objects.Create(client, containerName, fileName, opt)</code></pre></div>



<p>objects.Createを利用してファイルをストレージに保存します</p>



<p>簡単ですが、以上がgophercloudを利用したファイル操作方法です</p>



<p>公開設定が行われている場合、以下のURLでファイルを閲覧することができます</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>http://localhost:8080/v1/AUTH_admin/container_name/file_name.jpg</code></pre></div>



<h2 class="wp-block-heading">以上</h2>



<p>簡単ですが、Dockerを利用したSwift環境の構築と、基本的な操作方法を紹介しました<br>ローカルにSwift環境が作成できれば、GMO ConoHaと環境を合わせることができるので、開発やテストの面で環境差異を減らすことができます</p>



<amp-ad width="300" height="250" type="a8" data-aid="181111897311" data-wid="001" data-eno="01" data-mid="s00000000018030036000" data-mat="2ZTUU1-555TWY-50-4YTR9D" data-type="static"></amp-ad>


<div id="rinkerid1021" class="yyi-rinker-contents  yyi-rinker-postid-1021 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-6 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/booxstore/cabinet/01139/bk4814400047.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">初めてのGo言語 他言語プログラマーのためのイディオマティックGo実践ガイド／JonBodner／武舎広幸【3000円以上送料無料】</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,960</span>
															<span class="price_at">(2026/04/18 17:14:50時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEGo%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3D%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>


<div id="rinkerid1159" class="yyi-rinker-contents  yyi-rinker-postid-1159 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-6 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FOpenStack%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/rakutenkobo-ebooks/cabinet/8994/2000004868994.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FOpenStack%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">OpenStack徹底活用テクニックガイド【電子書籍】[ 澤橋松王 ]</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,643</span>
															<span class="price_at">(2026/04/18 17:14:50時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=OpenStack&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FOpenStack%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DOpenStack" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2025/04/docker%e3%81%a7openstack-swift%e3%81%ae%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e3%83%86%e3%82%b9%e3%83%88%e7%92%b0%e5%a2%83%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b/">DockerでOpenStack Swiftのローカルテスト環境を作成する</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2025/04/docker%e3%81%a7openstack-swift%e3%81%ae%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e3%83%86%e3%82%b9%e3%83%88%e7%92%b0%e5%a2%83%e3%82%92%e4%bd%9c%e6%88%90%e3%81%99%e3%82%8b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>一言メモ：OpenSearchServiceで処理反映まで待つ方法</title>
		<link>https://sheltie-garage.xyz/tech/2024/07/%e4%b8%80%e8%a8%80%e3%83%a1%e3%83%a2%ef%bc%9aopensearchservice%e3%81%a7%e5%87%a6%e7%90%86%e5%8f%8d%e6%98%a0%e3%81%be%e3%81%a7%e5%be%85%e3%81%a4%e6%96%b9%e6%b3%95/</link>
					<comments>https://sheltie-garage.xyz/tech/2024/07/%e4%b8%80%e8%a8%80%e3%83%a1%e3%83%a2%ef%bc%9aopensearchservice%e3%81%a7%e5%87%a6%e7%90%86%e5%8f%8d%e6%98%a0%e3%81%be%e3%81%a7%e5%be%85%e3%81%a4%e6%96%b9%e6%b3%95/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 07 Jul 2024 13:08:15 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[OpenSearch]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=1084</guid>

					<description><![CDATA[<p>現象 個人的に作成しているアプリで、OpenSearchに更新を実施後、すぐに検索を行うと削除したはずの記事が検索結果に含まれてしまうOpenSeearchへのアクセスにはgo-clientを使用している 対応方法 De [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2024/07/%e4%b8%80%e8%a8%80%e3%83%a1%e3%83%a2%ef%bc%9aopensearchservice%e3%81%a7%e5%87%a6%e7%90%86%e5%8f%8d%e6%98%a0%e3%81%be%e3%81%a7%e5%be%85%e3%81%a4%e6%96%b9%e6%b3%95/">一言メモ：OpenSearchServiceで処理反映まで待つ方法</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">現象</h2>



<p>個人的に作成しているアプリで、OpenSearchに更新を実施後、すぐに検索を行うと削除したはずの記事が検索結果に含まれてしまう<br>OpenSeearchへのアクセスにはgo-clientを使用している</p>



<h2 class="wp-block-heading">対応方法</h2>



<p>Deleteリクエストを送信する際のパラメータを、以下のように設定する</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>	deleteReq := opensearchapi.DocumentDeleteReq{
		Index:      &quot;index&quot;,
		DocumentID: 1,
		Params: opensearchapi.DocumentDeleteParams{
			Refresh: &quot;wait_for&quot;,
		},
	}</code></pre></div>



<p>Refresh: &#8220;wait_for&#8221;を指定することで、削除が反映されるまでリクエストが待機されます(デフォルトはfalse)</p>



<h2 class="wp-block-heading">参考</h2>



<p><a href="https://zenn.dev/kyo18/articles/b8409bff18d277">elasticsearchのrefreshに関して</a></p>



<p><a href="https://opensearch.org/docs/latest/api-reference/document-apis/delete-by-query/">Delete by query</a></p>



<h2 class="wp-block-heading">宣伝</h2>


<div id="rinkerid1021" class="yyi-rinker-contents  yyi-rinker-postid-1021 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/booxstore/cabinet/01139/bk4814400047.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">初めてのGo言語 他言語プログラマーのためのイディオマティックGo実践ガイド／JonBodner／武舎広幸【3000円以上送料無料】</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,960</span>
															<span class="price_at">(2026/04/18 17:14:50時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEGo%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3D%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2024/07/%e4%b8%80%e8%a8%80%e3%83%a1%e3%83%a2%ef%bc%9aopensearchservice%e3%81%a7%e5%87%a6%e7%90%86%e5%8f%8d%e6%98%a0%e3%81%be%e3%81%a7%e5%be%85%e3%81%a4%e6%96%b9%e6%b3%95/">一言メモ：OpenSearchServiceで処理反映まで待つ方法</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2024/07/%e4%b8%80%e8%a8%80%e3%83%a1%e3%83%a2%ef%bc%9aopensearchservice%e3%81%a7%e5%87%a6%e7%90%86%e5%8f%8d%e6%98%a0%e3%81%be%e3%81%a7%e5%be%85%e3%81%a4%e6%96%b9%e6%b3%95/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>初めてのGo言語</title>
		<link>https://sheltie-garage.xyz/tech/2024/04/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aego%e8%a8%80%e8%aa%9e/</link>
					<comments>https://sheltie-garage.xyz/tech/2024/04/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aego%e8%a8%80%e8%aa%9e/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 07 Apr 2024 08:30:38 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=1019</guid>

					<description><![CDATA[<p>初めてのGo言語という本を読み終わったので、軽く書評を残しておこうと思います。 書評:Goの基本文法から単体テスト、標準パッケージまでがまとめられた1冊 Go言語の基本文法からGoルーチン、ジェネリクス、標準パッケージま [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2024/04/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aego%e8%a8%80%e8%aa%9e/">初めてのGo言語</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>初めてのGo言語という本を読み終わったので、軽く書評を残しておこうと思います。</p>



<h2 class="wp-block-heading">書評:Goの基本文法から単体テスト、標準パッケージまでがまとめられた1冊</h2>



<p>Go言語の基本文法からGoルーチン、ジェネリクス、標準パッケージまでがまとめられた一冊で、Tour of Goよりももっと深い知識が手に入ります。<br>ひとまずGoを一通り理解したいという方にはお勧めできる1冊でした。</p>



<p>Goは比較的シンプルな言語構文となっていますが、後半のトピックスであるポインタ、並列処理、テスト、ジェネリクスあたりになってくると、さすがに手を動かさないと自分は理解できないレベルでした。</p>



<p>Go言語はかなり癖が強い(iotaやrune形など)仕様もあったりするので、体系的に言語仕様が解説された書籍は1冊手元に置いておくとよいと思いました。</p>



<h2 class="wp-block-heading">自分が購入した目的</h2>



<p>自分はEchoというライブラリを利用してWebサービスを趣味で作成しているのですが、Tour Of Goの知識をもとに、なんとなく開発を進めていました。<br>ただ、開発を進めていくうえでもう少しきちんとした知識を身に着けておきたいと思い、本書を購入しました。<br>内容としては十分すぎるほどで、特に標準パッケージ、テスト、インターフェース、エラー処理について参考にできそうでした。</p>


<div id="rinkerid1021" class="yyi-rinker-contents  yyi-rinker-postid-1021 yyi-rinker-img-m yyi-rinker-catid-16 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/booxstore/cabinet/01139/bk4814400047.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">初めてのGo言語 他言語プログラマーのためのイディオマティックGo実践ガイド／JonBodner／武舎広幸【3000円以上送料無料】</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,960</span>
															<span class="price_at">(2026/04/18 17:14:50時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEGo%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3D%25E5%2588%259D%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25AEGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>



<p></p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2024/04/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aego%e8%a8%80%e8%aa%9e/">初めてのGo言語</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2024/04/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aego%e8%a8%80%e8%aa%9e/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Go+Echoでやってみるスキーマ駆動開発</title>
		<link>https://sheltie-garage.xyz/tech/2023/11/goecho%e3%81%a7%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b%e3%82%b9%e3%82%ad%e3%83%bc%e3%83%9e%e9%a7%86%e5%8b%95%e9%96%8b%e7%99%ba/</link>
					<comments>https://sheltie-garage.xyz/tech/2023/11/goecho%e3%81%a7%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b%e3%82%b9%e3%82%ad%e3%83%bc%e3%83%9e%e9%a7%86%e5%8b%95%e9%96%8b%e7%99%ba/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 12 Nov 2023 13:13:40 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=926</guid>

					<description><![CDATA[<p>スキーマ駆動開発とはシステム開発において複数のシステムを結合する際に共通となる標準的なスキーマを用いてインターフェースを設計し開発を進める手法の一つです。WebAPIの定義記述においてはOpenAPI、プロトコルとしてG [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/11/goecho%e3%81%a7%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b%e3%82%b9%e3%82%ad%e3%83%bc%e3%83%9e%e9%a7%86%e5%8b%95%e9%96%8b%e7%99%ba/">Go+Echoでやってみるスキーマ駆動開発</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>スキーマ駆動開発とは<br>システム開発において複数のシステムを結合する際に共通となる標準的なスキーマを用いてインターフェースを設計し開発を進める手法の一つです。<br>WebAPIの定義記述においてはOpenAPI、プロトコルとしてGraphQL, gRPCなどが存在します。</p>
<cite>https://www.arsaga.jp/news/dx-technical-glossary/%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA/#:~:text=%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%81%A8%E3%81%AF,%E3%81%AA%E3%81%A9%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82</cite></blockquote>



<p>ということで、ざっくりお伝えするとWebAPIのパラメータ部分を先に設計して、それに合わせてビジネスロジックを作り込んでいく手法・・・と、中の人は理解しています。</p>



<p>今回はGo + Echo + OpenAPIを利用してスキーマ駆動開発を実践しようと思います。</p>



<h2 class="wp-block-heading">エディタのセットアップ</h2>



<p>OpenAPIに準拠した仕様書をYAMLで記述するためにVS Codeに拡張機能をインストールします。<br>今回は「OpenAPI (Swagger) Editor」を利用しました。</p>



<p>これで、VS Code上でプレビューしつつ仕様書を書くことが出来ます。<br>(下画像赤枠でプレビューが表示できます)</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="724" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112-1024x724.png" alt="" class="wp-image-927" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112-1024x724.png 1024w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112-300x212.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112-768x543.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112-1536x1085.png 1536w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112.png 1922w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">スキーマ定義書の作成</h2>



<p>エディタの設定が終わったので、実際に定義を作成します。<br>今回はシンプルに名前とE-Mailを受け取るだけのWebAPIとしました。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>openapi: 3.0.0
info:
  version: 1.0.0
  title: RIDE-Content
  description: &gt;-
    ユーザー名とE-Mailを受け取り、受け取った値をそのまま返却します。
servers:
  - url: &#39;http://localhost:1232&#39;
    description: ローカル環境
paths:
  /user:
    post:
      description: &gt;
        ユーザー名とE-Mailを受け取り、その値を返却する
      operationId: user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: &quot;#/components/schemas/UserSampleRequest&quot;
      responses:
        &#39;200&#39;:
          description: &quot;登録成功&quot;
          content:
            application/json:
              schema:
                $ref: &#39;#/components/schemas/UserSampleResponse&#39;
        &#39;400&#39;:
          description: &quot;リクエストのバリデーションエラー&quot;
          content:
            application/json:
              schema:
                $ref: &#39;#/components/schemas/Error&#39;
        &#39;500&#39;:
          description: &quot;内部エラー&quot;
          content:
            application/json:
              schema:
                $ref: &#39;#/components/schemas/Error&#39;
components:
  schemas:
    UserSampleRequest:
      type: &quot;object&quot;
      required:
        - &quot;name&quot;
        - &quot;email&quot;
      properties:
        name:
          type: &quot;string&quot;
          x-go-type: string
          example: &quot;test_name&quot;
          description: &quot;ユーザー名&quot;
        email:
          type: &quot;string&quot;
          x-go-type: string
          example: &quot;test@mail.com&quot;
          description: &quot;パスワード&quot;
    UserSampleResponse:
      type: &quot;boolean&quot;
      x-go-type: bool
      example: true
      description: &quot;true:処理成功、false:処理失敗&quot;
    Error:
      type: &quot;object&quot;
      properties:
        error:
          type: &quot;string&quot;
          example: &quot;ここにエラーメッセージが設定されます&quot;
          description: &quot;エラーメッセージ&quot;
externalDocs:
  description: &quot;Find out more about Swagger&quot;
  url: &quot;http://swagger.io&quot;</code></pre></div>



<h2 class="wp-block-heading">Go + Echoのセットアップ</h2>



<p>先程作成したOpenAPIの定義書を元に、WebAPIを作成します。<br>まずはGO + Echoのプロジェクトを作成します。</p>



<p>プロジェクトのディレクトリに移動し、以下のコマンドでセットアップを行います。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>go mod init sdd
go get github.com/labstack/echo/v4</code></pre></div>



<p>これでEchoのプロジェクトが作成されました。</p>



<h2 class="wp-block-heading">OpenAPIの定義書からGoのソースを作成する</h2>



<p>今回は「<a href="https://github.com/deepmap/oapi-codegen">oapi-codegen</a>」を利用しました。<br>Go用のソースコードジェネレータはいくつかありますが、oapi-codegenは「生成するソースが1つのみ」ということで、一番シンプルに扱えそうだったため、今回使用することにしました。<br>下記コマンドでインストールします。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest</code></pre></div>



<p>インストールが終わったら、以下のコマンドでyamlファイルからGoソースを生成します。<br>先程作成したOpenAPIの定義ファイル(ymlファイル)、パッケージ名、出力されるファイル名を指定します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>oapi-codegen -package sdd openapi.yaml &gt; sdd.gen.go
go mod tidy</code></pre></div>



<p>oapi-codegenはmain関数は生成しないので、自分で定義する必要があります。<br>実際にmain関数を作成し、動作を確認してみます。</p>



<h2 class="wp-block-heading">main関数を作成する</h2>



<p>main関数を作成します。<br>普通のGoプログラムのため、Echoのサンプルに基づいて作成します。<br>(Echoのサンプルを元に作ったので、ファイル名はserver.goという名前にしました)</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>package main

import (
	&quot;net/http&quot;
	&quot;sdd/sdd&quot;

	&quot;github.com/labstack/echo/v4&quot;
)

type webapi struct{}

func (w webapi) User(ctx echo.Context) error {

	var reqBody sdd.UserSampleRequest
	ctx.Bind(&reqBody)

	return ctx.JSON(http.StatusOK, reqBody)
}

func main() {
	e := echo.New()

	api := webapi{}
	sdd.RegisterHandlers(e, api)

	e.Logger.Fatal(e.Start(&quot;:1323&quot;))
}
</code></pre></div>



<p>この時点で、ディレクトリ構成は以下のようになっています。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="638" height="332" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_002.png" alt="" class="wp-image-929" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_002.png 638w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_002-300x156.png 300w" sizes="auto, (max-width: 638px) 100vw, 638px" /></figure>



<h2 class="wp-block-heading">動作を確認してみる</h2>



<p>server.goをVS Codeのデバッグモードで実行し、動作を確認してみます。<br>WebAPIのエントリポイントと、渡すべきデータはOpenAPIの定義書で定義済みとなりますので、その値を利用します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="779" height="1024" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_003-779x1024.png" alt="" class="wp-image-930" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_003-779x1024.png 779w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_003-228x300.png 228w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_003-768x1010.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_003.png 888w" sizes="auto, (max-width: 779px) 100vw, 779px" /></figure>



<p>POSTMANを利用して、リクエストを実行しました。<br>送信した値がそのままレスポンスとして帰ってきましたので、動作は大丈夫そうです。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="541" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_004-1024x541.png" alt="" class="wp-image-931" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_004-1024x541.png 1024w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_004-300x158.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_004-768x406.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_004-1536x811.png 1536w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/11/20231112_004-2048x1082.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">以上です</h2>



<p>ということで、ざっくりですがGo + Echoを利用したスキーマ駆動開発の紹介を行いました。<br>OpenAPIの仕様に基づいた定義を行うことで、設計書とAPIの実装がズレてしまう、ということも防げるかと思います。</p>



<p>自分は今まで個人開発を行うときに設計書は書いていなかったのですが、今後はOpenAPIの定義書をちゃんと作って開発を行っていきたいと思いました。<br>(API一覧が確認できたり、APIの仕様がまとまっている資料というのは、後々助かる資料になるので)</p>


<div id="rinkerid932" class="yyi-rinker-contents  yyi-rinker-postid-932 yyi-rinker-img-m yyi-rinker-catid-16 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FWebAPI%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/7015/9784798167015.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FWebAPI%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">Web APIの設計 （Programmer&#8217;s SELECTION） [ Arnaud Lauret ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥4,180</span>
															<span class="price_at">(2026/04/19 15:12:46時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=WebAPI&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FWebAPI%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DWebAPI" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>


<div id="rinkerid933" class="yyi-rinker-contents  yyi-rinker-postid-933 yyi-rinker-img-m yyi-rinker-catid-16 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%259E%25E3%2582%25A4%25E3%2582%25AF%25E3%2583%25AD%25E3%2582%25B5%25E3%2583%25BC%25E3%2583%2593%25E3%2582%25B9%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/0010/9784814400010_1_2.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%259E%25E3%2582%25A4%25E3%2582%25AF%25E3%2583%25AD%25E3%2582%25B5%25E3%2583%25BC%25E3%2583%2593%25E3%2582%25B9%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">マイクロサービスアーキテクチャ 第2版 [ Sam Newman ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E3%2583%259E%25E3%2582%25A4%25E3%2582%25AF%25E3%2583%25AD%25E3%2582%25B5%25E3%2583%25BC%25E3%2583%2593%25E3%2582%25B9%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3D%25E3%2583%259E%25E3%2582%25A4%25E3%2582%25AF%25E3%2583%25AD%25E3%2582%25B5%25E3%2583%25BC%25E3%2583%2593%25E3%2582%25B9" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/11/goecho%e3%81%a7%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b%e3%82%b9%e3%82%ad%e3%83%bc%e3%83%9e%e9%a7%86%e5%8b%95%e9%96%8b%e7%99%ba/">Go+Echoでやってみるスキーマ駆動開発</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2023/11/goecho%e3%81%a7%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b%e3%82%b9%e3%82%ad%e3%83%bc%e3%83%9e%e9%a7%86%e5%8b%95%e9%96%8b%e7%99%ba/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OpenSearchでなにか作るぞ!(その6 アイコンデータを検索出来るようにサーバーサイドを修正する）</title>
		<link>https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae6-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e6%a4%9c%e7%b4%a2%e5%87%ba/</link>
					<comments>https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae6-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e6%a4%9c%e7%b4%a2%e5%87%ba/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sat, 19 Aug 2023 11:20:36 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[OpenSearch]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=848</guid>

					<description><![CDATA[<p>前回まででOpenSearchのインデックスにアイコンデータを組み込むところまで作成しました。今回は追加したアイコンデータを検索できるように、Goで作成しているサーバーサイドの更新を行います。 クエリの形式を変更する 今 [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae6-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e6%a4%9c%e7%b4%a2%e5%87%ba/">OpenSearchでなにか作るぞ!(その6 アイコンデータを検索出来るようにサーバーサイドを修正する）</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>前回まででOpenSearchのインデックスにアイコンデータを組み込むところまで作成しました。<br>今回は追加したアイコンデータを検索できるように、Goで作成しているサーバーサイドの更新を行います。</p>



<h2 class="wp-block-heading">クエリの形式を変更する</h2>



<p>今まではQueryDSLを利用してクエリを構築していましたが、これをプログラムで作成しようとするとなかなか苦労しそうで、いい方法が思いつきませんでした。</p>



<p>ということで、今回から「Query String」という形式を利用してクエリを発行することにしました。<br><a href="https://opensearch.org/docs/latest/query-dsl/full-text/query-string/" target="_blank" rel="noreferrer noopener">https://opensearch.org/docs/latest/query-dsl/full-text/query-string/</a></p>



<p>この形式であればJSONの複雑な構造ではなく、シンプルな文字列でクエリを表現できそうだったため、この形式を利用することにしました。</p>



<h2 class="wp-block-heading">クエリ生成部分の修正</h2>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>	queryMainStr := `{
		&quot;size&quot;: 20,
		&quot;query&quot;: {
			&quot;query_string&quot;: {
				&quot;query&quot;: &quot;%s&quot;
			}
		}
	}`</code></pre></div>



<p>query_stringを利用し、%sの部分をクエリストリングに置き換える。<br>QueryDSLよりもシンプルにすることが出来ました。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>	queryStr := &quot;&quot;
	if searchRequest.Keyword != &quot;&quot; {
		queryStr += &quot;work_title:&quot; + searchRequest.Keyword
	}
	if searchRequest.AgeLimitType != &quot;&quot; {
		if queryStr != &quot;&quot; {
			queryStr += &quot; AND &quot;
		}
		queryStr += &quot;work_icons:&quot; + searchRequest.AgeLimitType
	}</code></pre></div>



<p>クエリ文字列を作成する部分です。<br>条件が2つしか存在しないので力技でANDをつけたりして組み立てています。<br>条件が今後増えてくれば、もう少しクエリ組み立て部分は考える必要が出てきそうですね。</p>



<p>組み立てたクエリは「fmt.Sprintf(クエリ文字列, クエリ式)」を利用して%sの部分を置き換えています。</p>



<h2 class="wp-block-heading">POSTMANから実行してみる</h2>



<p>POSTMANから実行してみます。<br>今回はクエリパラメータに条件を設定し、GETパラメータでサーバーに渡します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="332" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_001-1024x332.png" alt="" class="wp-image-849" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_001-1024x332.png 1024w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_001-300x97.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_001-768x249.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_001-1536x498.png 1536w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_001-2048x665.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>実行した結果はこちらになります。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="558" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_002-1024x558.png" alt="" class="wp-image-850" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_002-1024x558.png 1024w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_002-300x163.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_002-768x418.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_002-1536x837.png 1536w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230819_002.png 2008w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>query_stringを利用して検索結果を取得することが出来ました。</p>



<h2 class="wp-block-heading">以上です</h2>



<p>今回はサーバーサイドの改修を行いました。<br>次回はフロントエンドの開発に入ろうかと思います。</p>


<div id="rinkerid851" class="yyi-rinker-contents  yyi-rinker-postid-851 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FReact%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/9163/9784297129163_1_4.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FReact%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発 [ 手島 拓也 ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,498</span>
															<span class="price_at">(2026/04/18 18:01:38時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=React&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FReact%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DReact" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>


<div id="rinkerid514" class="yyi-rinker-contents  yyi-rinker-postid-514 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/5196/9784297125196_1_3.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">エキスパートたちのGo言語　一流のコードから応用力を学ぶ [ 上田 拓也 ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,278</span>
															<span class="price_at">(2026/04/18 18:23:54時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=Go%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae6-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e6%a4%9c%e7%b4%a2%e5%87%ba/">OpenSearchでなにか作るぞ!(その6 アイコンデータを検索出来るようにサーバーサイドを修正する）</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae6-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e6%a4%9c%e7%b4%a2%e5%87%ba/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OpenSearchでなにか作るぞ!(その5 アイコンデータに対応させる）</title>
		<link>https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae5-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ab%e5%af%be%e5%bf%9c%e3%81%95/</link>
					<comments>https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae5-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ab%e5%af%be%e5%bf%9c%e3%81%95/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 06 Aug 2023 08:18:31 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[OpenSearch]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=824</guid>

					<description><![CDATA[<p>前回までで一旦OpenSearchにドキュメントを登録するところまで出来ました。今回はカラムにArrayタイプのデータを登楼して、アイコン(DAnimeで言うR15+やレンタルなど)を検索出来るようにします。 OpenS [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae5-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ab%e5%af%be%e5%bf%9c%e3%81%95/">OpenSearchでなにか作るぞ!(その5 アイコンデータに対応させる）</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>前回までで一旦OpenSearchにドキュメントを登録するところまで出来ました。<br>今回はカラムにArrayタイプのデータを登楼して、アイコン(DAnimeで言うR15+やレンタルなど)を検索出来るようにします。</p>



<h2 class="wp-block-heading">OpenSearchのMappingを改修する</h2>



<p>現在のマッピング定義にアイコン情報を格納するカラムが存在しないので、追加します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>・・・省略
        &quot;end_of_delivery&quot;: {
        &quot;type&quot;: &quot;integer&quot;
        },
        &quot;work_icons&quot;:{　←これを追加
          &quot;type&quot; : &quot;keyword&quot;
        },
        &quot;created_at&quot;: {
        &quot;type&quot;: &quot;date&quot;
        },
        &quot;updated_at&quot;: {
        &quot;type&quot;: &quot;date&quot;
        }
・・・省略</code></pre></div>



<p>ちなみに、OpenSearchには「Array型」というものは存在しないようで、上記のように通常のカラムを追加し、登録時に配列でデータを渡すことで1カラムに複数データを格納できる仕様になっているみたいです。</p>



<h2 class="wp-block-heading">BulkInsertバッチを改修する</h2>



<p>マッピングが修正できたら、バルクインサートバッチを改修します。<br>DBに保存しているアイコン情報をgroup_condatでカンマ区切りで取得し、OpenSearch登録時にカンマ区切りから配列に変換して登録して見るようにしました。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>・・・省略
	&quot; ,IFNULL(group_concat(a_icon.work_icons), &#39;&#39;) AS work_icons &quot; +　←ここを追加
	&quot; ,a_list.created_at&quot; +
	&quot; ,a_list.updated_at&quot; +
	&quot; FROM d_anime.anime_list a_list &quot; +
	&quot; LEFT JOIN d_anime.work_icon a_icon &quot; +
	&quot; ON a_list.work_id = a_icon.work_id &quot; +
	&quot; GROUP BY a_list.work_id&quot;</code></pre></div>



<p>OpenSearch登録用の構造体を別途作成し、アイコン情報を配列に変換して渡してみます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>・・・省略
		tmp.EndOfDelivery = result[i].EndOfDelivery
		if result[i].WorkIcons == &quot;&quot; {
			tmp.WorkIcons = []string{}　←データが無ければ、空の配列を設定
		} else {
			tmp.WorkIcons = strings.Split(result[i].WorkIcons, &quot;,&quot;) ← カンマ区切りから配列に変更
		}
		tmp.CreatedAt = result[i].CreatedAt
		tmp.UpdatedAt = result[i].UpdatedAt
・・・省略</code></pre></div>



<p>実際にバルクインサート用のデータを作成すると、以下のようになります。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>R15作品の例
{ &quot;index&quot; : { &quot;_index&quot; : &quot;d_anime&quot;, &quot;_id&quot; : &quot;7a26cf047bd32d6771cc68057834d37d15d30eee4dfc6d6e62bcb9450d7faff1&quot; } }
{&quot;work_id&quot;:24959,&quot;work_title&quot;:&quot;みこすり半劇場&quot;,&quot;link&quot;:&quot;https://animestore.docomo.ne.jp/animestore/ci?workId=24959&quot;,&quot;main_key_visual_path&quot;:&quot;https://cs1.animestore.docomo.ne.jp/anime_kv/img/24/95/9/24959_1_2.png?1627875034000&quot;,&quot;main_key_visual_alt&quot;:&quot;みこすり半劇場_2&quot;,&quot;my_list_count&quot;:2519,&quot;favorite_count&quot;:2644,&quot;age_limit_type&quot;:2,&quot;end_of_delivery&quot;:0,&quot;work_icons&quot;:[&quot;r15&quot;],&quot;created_at&quot;:&quot;2023-07-16T16:27:00+09:00&quot;,&quot;updated_at&quot;:&quot;2023-07-16T16:27:00+09:00&quot;}</code></pre></div>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>アイコン情報が無い作品の例
{ &quot;index&quot; : { &quot;_index&quot; : &quot;d_anime&quot;, &quot;_id&quot; : &quot;74b3114fda6e38fe1c36f5cbd0909c955d3e47d47fcf98d808075e3a8f4cbc5a&quot; } }
{&quot;work_id&quot;:24953,&quot;work_title&quot;:&quot;マギアレコード 魔法少女まどか☆マギカ外伝 Final SEASON –浅き夢の暁-&quot;,&quot;link&quot;:&quot;https://animestore.docomo.ne.jp/animestore/ci?workId=24953&quot;,&quot;main_key_visual_path&quot;:&quot;https://cs1.animestore.docomo.ne.jp/anime_kv/img/24/95/3/24953_1_2.png?1647568836875&quot;,&quot;main_key_visual_alt&quot;:&quot;マギアレコード 魔法少女まどか☆マギカ外伝 Final SEASON –浅き夢の暁-_2&quot;,&quot;my_list_count&quot;:12820,&quot;favorite_count&quot;:26865,&quot;age_limit_type&quot;:0,&quot;end_of_delivery&quot;:0,&quot;work_icons&quot;:[],&quot;created_at&quot;:&quot;2023-07-16T16:26:45+09:00&quot;,&quot;updated_at&quot;:&quot;2023-07-16T16:26:45+09:00&quot;}</code></pre></div>



<h2 class="wp-block-heading">検索を行い、確認する</h2>



<p>これでアイコン情報がインデックスに登録出来たので、検索出来るのか確認してみます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="482" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_001-1024x482.png" alt="" class="wp-image-825" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_001-1024x482.png 1024w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_001-300x141.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_001-768x362.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_001-1536x723.png 1536w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_001.png 1915w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>R15作品を検索したところ、18作品ヒットしました。そのうちの一つを実際のサイトで確認してみます。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="979" height="607" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_002.png" alt="" class="wp-image-826" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_002.png 979w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_002-300x186.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/08/20230806_002-768x476.png 768w" sizes="auto, (max-width: 979px) 100vw, 979px" /></figure>



<p>土下座で頼んでみた　を確認したところ、きちんとR15指定の作品になっていました。<br>これで、レンタルや期間限定、R15作品を個別に検索するための下準備を作ることが出来ました。</p>



<p>R15作品については、本当に正しい検索結果になっているか検証が必要なので、本日はこのあたりで失礼します。</p>


<div id="rinkerid775" class="yyi-rinker-contents  yyi-rinker-postid-775 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=monodon-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow"><img decoding="async" src="https://m.media-amazon.com/images/I/51Y0-P+m94L._SL160_.jpg" width="112" height="160" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=monodon-22&#038;linkCode=ogi&#038;th=1&#038;psc=1" rel="nofollow">モダンJavaScriptの基本から始める　React実践の教科書　（最新ReactHooks対応）</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/dp/B09BV2HGN3?tag=monodon-22&amp;linkCode=ogi&amp;th=1&amp;psc=1" rel="nofollow" class="yyi-rinker-link">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=react&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2Freact%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3Dreact" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>


<div id="rinkerid645" class="yyi-rinker-contents  yyi-rinker-postid-645 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/9694/9784873119694_1_3.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">実用 Go言語 システム開発の現場で知っておきたいアドバイス [ 渋川 よしき ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,960</span>
															<span class="price_at">(2026/04/18 17:55:08時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=Go%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae5-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ab%e5%af%be%e5%bf%9c%e3%81%95/">OpenSearchでなにか作るぞ!(その5 アイコンデータに対応させる）</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2023/08/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9e%e3%81%9d%e3%81%ae5-%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b3%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ab%e5%af%be%e5%bf%9c%e3%81%95/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OpenSearchでなにか作るぞ!(dAnimeリメイク 番外編 バグ修正)</title>
		<link>https://sheltie-garage.xyz/tech/2023/07/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9edanime%e3%83%aa%e3%83%a1%e3%82%a4%e3%82%af-%e7%95%aa%e5%a4%96%e7%b7%a8-%e3%83%90%e3%82%b0%e4%bf%ae%e6%ad%a3/</link>
					<comments>https://sheltie-garage.xyz/tech/2023/07/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9edanime%e3%83%aa%e3%83%a1%e3%82%a4%e3%82%af-%e7%95%aa%e5%a4%96%e7%b7%a8-%e3%83%90%e3%82%b0%e4%bf%ae%e6%ad%a3/#respond</comments>
		
		<dc:creator><![CDATA[monodon]]></dc:creator>
		<pubDate>Sun, 23 Jul 2023 13:29:04 +0000</pubDate>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[OpenSearch]]></category>
		<guid isPermaLink="false">https://sheltie-garage.xyz/tech/?p=816</guid>

					<description><![CDATA[<p>前回形態素解析にsudachiを導入しました。そのとき、データ再作成のためにbulk insertを実行したのですが、これが正しく動いていないことに気づいたので、こちらを修正していきます。 Work IDが正しく設定され [&#8230;]</p>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/07/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9edanime%e3%83%aa%e3%83%a1%e3%82%a4%e3%82%af-%e7%95%aa%e5%a4%96%e7%b7%a8-%e3%83%90%e3%82%b0%e4%bf%ae%e6%ad%a3/">OpenSearchでなにか作るぞ!(dAnimeリメイク 番外編 バグ修正)</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></description>
										<content:encoded><![CDATA[
<p>前回形態素解析にsudachiを導入しました。<br>そのとき、データ再作成のためにbulk insertを実行したのですが、これが正しく動いていないことに気づいたので、こちらを修正していきます。</p>



<h2 class="wp-block-heading">Work IDが正しく設定されていないことに気づく</h2>



<p>OpenSearch Dashboardからデータを確認したら、WorkIdが設定されていないことに気づきました。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="601" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_001-1024x601.png" alt="" class="wp-image-817" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_001-1024x601.png 1024w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_001-300x176.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_001-768x451.png 768w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_001.png 1142w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>MySQLにはデータは正しく登録されているため、Go側の登録処理に問題があると思い処理を見直したところ、WorkIDが「文字列」として生成されており、OpenSearchに登録されていないことが分かりました。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="830" height="192" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/202307023_002.png" alt="" class="wp-image-818" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/202307023_002.png 830w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/202307023_002-300x69.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/202307023_002-768x178.png 768w" sizes="auto, (max-width: 830px) 100vw, 830px" /></figure>



<h2 class="wp-block-heading">json,Marshalは構造体のデータ構造に基づいてJSONを生成する</h2>



<p>Bulk Insertを実行したときの大まかなデータの流れは以下の通り<br>DBよりデータ抽出→Goの構造体にデータを格納→json.Marshalを利用して構造体をJSONに変換→OpenSearchに登録</p>



<p>json.Marshalを実行したときに、int型で出力されてほしいデータがstringで出力されていたのでなんでかなと思ったら、構造体がstring型で定義されていただけという落ちでした。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1000" height="342" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_003.png" alt="" class="wp-image-819" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_003.png 1000w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_003-300x103.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_003-768x263.png 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<p>WorkIdのプロパティをintに変更することで、無事にint型として出力され、OpenSearch側にも登録されました。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="758" height="204" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/スクリーンショット-2023-07-23-22.23.51.png" alt="" class="wp-image-820" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/スクリーンショット-2023-07-23-22.23.51.png 758w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/スクリーンショット-2023-07-23-22.23.51-300x81.png 300w" sizes="auto, (max-width: 758px) 100vw, 758px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="969" height="548" src="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_004.png" alt="" class="wp-image-821" srcset="https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_004.png 969w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_004-300x170.png 300w, https://sheltie-garage.xyz/tech/wp-content/uploads/2023/07/20230723_004-768x434.png 768w" sizes="auto, (max-width: 969px) 100vw, 969px" /></figure>



<p>今更ながら、DB構造、Goの構造体、OpenSearchのインデックスそれぞれでデータ型を合わせておかないと変な場所でハマりますよという教訓でした。</p>


<div id="rinkerid645" class="yyi-rinker-contents  yyi-rinker-postid-645 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/9694/9784873119694_1_3.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">実用 Go言語 システム開発の現場で知っておきたいアドバイス [ 渋川 よしき ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,960</span>
															<span class="price_at">(2026/04/18 17:55:08時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=Go%E8%A8%80%E8%AA%9E&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2FGo%25E8%25A8%2580%25E8%25AA%259E%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3DGo%25E8%25A8%2580%25E8%25AA%259E" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>


<div id="rinkerid546" class="yyi-rinker-contents  yyi-rinker-postid-546 yyi-rinker-img-m yyi-rinker-catid-16 yyi-rinker-catid-18 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2585%25A8%25E6%2596%2587%25E6%25A4%259C%25E7%25B4%25A2%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/rakutenkobo-ebooks/cabinet/9422/2000005109422.jpg?_ex=128x128" width="128" height="128" class="yyi-rinker-main-img" style="border: none;" loading="lazy"></a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://af.moshimo.com/af/c/click?a_id=3394378&#038;p_id=54&#038;pc_id=54&#038;pl_id=616&#038;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2585%25A8%25E6%2596%2587%25E6%25A4%259C%25E7%25B4%25A2%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow">［改訂第3版］Apache Solr入門 ーオープンソース全文検索エンジン【電子書籍】[ 打田智子(著) ]</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥4,180</span>
															<span class="price_at">(2026/04/18 18:07:45時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/gp/search?ie=UTF8&amp;keywords=%E5%85%A8%E6%96%87%E6%A4%9C%E7%B4%A2&amp;tag=monodon-22&amp;index=blended&amp;linkCode=ure&amp;creative=6339" rel="nofollow" class="yyi-rinker-link">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616&amp;url=https%3A%2F%2Fsearch.rakuten.co.jp%2Fsearch%2Fmall%2F%25E5%2585%25A8%25E6%2596%2587%25E6%25A4%259C%25E7%25B4%25A2%2F%3Ff%3D1%26grp%3Dproduct" rel="nofollow" class="yyi-rinker-link">楽天市場</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3394378&amp;p_id=54&amp;pc_id=54&amp;pl_id=616" width="1" height="1" style="border:none;">					</li>
													<li class="yahoolink">
						<a href="https://af.moshimo.com/af/c/click?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502&amp;url=https%3A%2F%2Fshopping.yahoo.co.jp%2Fsearch%3Fp%3D%25E5%2585%25A8%25E6%2596%2587%25E6%25A4%259C%25E7%25B4%25A2" rel="nofollow" class="yyi-rinker-link">Yahooショッピング</a><img loading="lazy" decoding="async" src="https://i.moshimo.com/af/i/impression?a_id=3442618&amp;p_id=1225&amp;pc_id=1925&amp;pl_id=18502" width="1" height="1" style="border:none;">					</li>
				                											</ul>
					</div>
	</div>
</div>
<p>投稿 <a href="https://sheltie-garage.xyz/tech/2023/07/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9edanime%e3%83%aa%e3%83%a1%e3%82%a4%e3%82%af-%e7%95%aa%e5%a4%96%e7%b7%a8-%e3%83%90%e3%82%b0%e4%bf%ae%e6%ad%a3/">OpenSearchでなにか作るぞ!(dAnimeリメイク 番外編 バグ修正)</a> は <a href="https://sheltie-garage.xyz/tech">Sheltie Garage Tech</a> に最初に表示されました。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sheltie-garage.xyz/tech/2023/07/opensearch%e3%81%a7%e3%81%aa%e3%81%ab%e3%81%8b%e4%bd%9c%e3%82%8b%e3%81%9edanime%e3%83%aa%e3%83%a1%e3%82%a4%e3%82%af-%e7%95%aa%e5%a4%96%e7%b7%a8-%e3%83%90%e3%82%b0%e4%bf%ae%e6%ad%a3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
