1人で赤ちゃん(4ヶ月)をお風呂に入れる時のタイムライン

ワンオペお風呂というのでしょうか。
自分1人で生後4ヶ月の赤ちゃんをお風呂に入れなくてはいけなくなったときに「どうやれば良いのだろう??」と不安になっていたので、どなたかの参考になればと記述します。

環境

  • 赤ちゃん:生後4ヶ月
  • 自動湯沸かし器あり
  • 湯船の保温機能あり
  • シャワーの温度がいまいち安定しない
  • 浴室・脱衣所に暖房器具なし

タイムライン

16:20

  • 居間から廊下(およびその先の脱衣所)につながる扉を開き、居間のエアコンの力で廊下経由で脱衣所を少しでも温める
  • お風呂の換気扇を止める
  • お風呂を沸かし始める。

16:20~16:55

  • 赤ちゃんをあやす
  • 赤ちゃんの着替えを居間に準備しておく(着せやすいように広げておいておく)
  • 脱衣所に自分の着替えおよび赤ちゃん用のバスタオル・おむつ・ボディクリーム・ガーゼハンカチを持っていく
  • 居間のカーテンを閉めておく

16:55

  • 赤ちゃんの機嫌が良さそうなら、赤ちゃんに先にお風呂に入ってくる旨を伝えて急ぎ風呂に入る
  • 赤ちゃんの機嫌が悪い場合は多少あやしつつ時には諦めて風呂に入る
    ※赤ちゃんはベビーベッド内

16:55~

  • 急いでお風呂に入る。脱衣所の扉および浴室の扉は少し開けておいて、一応赤ちゃんの声が耳に入るようにする
  • 浴室にタオルも持って入る
  • 自分の体を洗う
  • 洗い終わったら浴室の床を一通り流して床が滑らないようにする
  • 持って入ったタオルで頭を乾かしつつ浴槽に1分程度浸かったら、浴室内で体を拭きつつ、赤ちゃんのお風呂用にボディソープや手桶を準備する
  • 浴室から出る前に、お風呂の椅子を拭いておく(後で座った時にひんやりしないように)
  • 浴室から出たら、赤ちゃん用のバスタオルをマントのように羽織り(洗濯バサミで首元でタオルを止める)、顔にクリームや髪の毛用クリームを塗る
  • ドライヤーで髪を乾かす
  • ガーゼハンカチを浴室の手桶の中に突っ込んでおく
  • 浴室の扉は閉めずに半ドアにしておく
  • 脱衣所にお風呂マット(我が家は、アイリスオーヤマ IRISOHYAMA BM-6085E ベージュ バスマット を使用。を敷き、自分が羽織っていたバスタオルを広げ、おむつやボディソープを並べておく)

17:05くらい〜

  • 脱衣所からベビーベットのある位置に向かう
  • ベビーベッドで赤ちゃんの衣服を脱がせ、おむつも脱がせる。おむつはゴミ箱に捨てる。
  • 赤ちゃんを抱えて浴室に向かう。
  • 赤ちゃんを膝の上に横向きに横たえ、頭の位置が右なら右腕で頭を支えて左手で赤ちゃんを洗う
  • 顔→頭→手→胴体→足・背中・お尻 の順でガーゼハンカチ・ボディソープ・手桶を使って洗っていく
  • 赤ちゃんの体を一通り洗ったら、手桶で浴室の床を一通り流した後、湯船に入る(泡の流し残しも湯船で落とし切る)
  • お風呂の自動温度調節機能を切る(赤ちゃんが入っている時に熱めのお湯が出てくる事態を防ぐ)
  • 湯船の中でガーゼハンカチを使って顔と耳・おへそを軽く拭く
  • 30秒数えて湯船から上がる

17:15くらい〜

  • 脱衣所に敷いておいたマットの上のバスタオルの上に赤ちゃんを横たえる
  • タオルで赤ちゃんの全身の水気をさっと拭き取る
  • バスタオル&タオルで赤ちゃんが寒くないように包む
  • 声をかけながら自分の体を拭く&服を着る
  • 服を着終わったら、赤ちゃんの全身の保湿を行う
  • おむつを履かせる

17:20くらい〜

  • 赤ちゃんを抱えて(タオル類は脱衣所に放置)、 居間に広げておいた赤ちゃんの服の元に連れていく
  • 赤ちゃんに服を着せる
  • 赤ちゃんの頭を布で乾かす

17:25くらい〜

  • 赤ちゃんと多少戯れる
  • ベビーベッドに放置していた赤ちゃんの脱いだ服を退け、必要に応じてシーツを交換した上で赤ちゃんをベビーベッドに戻す
  • 脱いだ服やシーツ・脱衣所のタオルなどの後片付けをしにいく

といったところでお風呂完了!

補足1:断念したやり方について

  • 大人がお風呂に入っている最中に脱衣所で待たせる
    → 赤ちゃんが不安がって大泣きしてしまったので断念しました。また脱衣所がそんなに暖かくないのでやめました。

  • 大人が風呂に入っている最中に浴室内で待たせる
    → 水や泡の飛沫が飛んでしまうのも気が気じゃないし、浴室もそこまで暖かくないのでやめました。

補足2:大人がお風呂に入っている間に赤ちゃんが泣き出した場合について

  • 浴室から赤ちゃんに向かって呼びかける
  • が、諦めることも多いです。
  • 泣き出すととても焦りますが、安全なベビーベッドの中にいるはずなのでゆったりとした心構えでいるようにしたら良いかと思います。

補足3:大人がお風呂に入っている際に赤ちゃんをベビーベットに置いておくことについて

  • ベビーベッドなら危険なものもないし少々目を離していても大丈夫ではと思い(夜はベビーベッドに寝かして大人は寝ますし・・・)、もちろん泣かれてもすぐには反応できないし一人ぼっちにするのは申し訳ないとは思いつつ、寒いよりかはいいかなと思っています。

補足4:赤ちゃんを床から持ち上げる時について

  • 重い荷物の持ち上げ方を参考に、自分の体を赤ちゃんになるべく近づけ、しっかりと腰を落として赤ちゃんを抱き、膝を伸ばして立ち上がる、ということを意識すると良いかと思います。
  • 日頃からスクワット等で足腰を鍛えておいた方が良いかと思います。YouTubeのスクワット動画等で日々スクワットをするようになってから格段に持ち上げが楽になりました。
  • 自分は立ち上がった瞬間にほんの少し頭がくらくらすることがあるので、立ち上がってすぐ歩き出すのではなく、少し立ち止まって頭がしゃんとしてから歩くようにしています。

goのmock使用中に「panic: reflect: NumIn of non-func type...」が起きた

環境

状況 ※ダメなコード例は面倒なので省略

  • mockを使ったテスト実施中に以下のようなエラーに遭遇する
panic: reflect: NumIn of non-func type *hoge.Huga [recovered]
    panic: reflect: NumIn of non-func type *hoge.Huga
  • stacktrace
goroutine 7 [running]:
testing.tRunner.func1.2(0x17e99c0, 0xc0002648c0)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/testing/testing.go:1143 +0x585
testing.tRunner.func1(0xc000224a80)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/testing/testing.go:1146 +0x3c8
panic(0x17e99c0, 0xc0002648c0)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/runtime/panic.go:971 +0x4c7
reflect.(*rtype).NumIn(0x18054e0, 0x0)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/reflect/type.go:984 +0x109
github.com/golang/mock/gomock.(*Call).DoAndReturn.func1(0xc000264840, 0x1, 0x1, 0x0, 0x0, 0x0)
    /Users/piyo/go/pkg/mod/github.com/golang/mock@v1.6.0/gomock/call.go:119 +0x166
(後略)

NumInとは?

  • reflect/type.goに記述あり。
NumIn returns a function type's input parameter count.
It panics if the type's Kind is not Func.

(関数の引数の個数を返す。関数じゃないものに対してこのメソッドが呼ばれるとpanicが起きる)

つまるところの原因

DoAndReturnのメソッドの使い方が誤っていた(構造体(*hoge.Huga)を渡していました)

  • DoAndReturnの使い方
DoAndReturn declares the action to run when the call is matched. The return values from this function are returned by the mocked function. It takes an interface{} argument to support n-arity functions.

(要約:モック対象の処理が呼ばれた時に実行してほしい関数を書く。モック対象の処理はその関数の戻り値を返却してくれる)

DoAndReturnメソッドは、n-arity functionのサポートのため、つまり関数の引数の個数が何個でも大丈夫なようにinterface型を引数として受け取れるようになっています。そのため、関数ではないものを渡したとしてもコンパイルエラーにはならず実行時にpanicが起こるようになっています。

参考

zenn.dev

感想(自戒)

  • 改めてエラーメッセージを読むと、初めから分かりやすく書いてあったんだなあと反省・・・(「NumInって何者!?」ってなって思考停止しておりました)
  • panicが発生した時はスタックトレースにきちんと目を通すのが大事
  • スタックトレースよくわからん、ってなったら(僕)デバッグを活用してどこで起きているのかを突き止めるのが大事
  • メソッドの使い方の説明文が英語だとしてもせいぜい数行、丁寧に読もう

grpcでサブディレクトリの中にprotoファイルと.pb.goファイルを入れたい

やりたいこと

・protoファイルをプロジェクトルート直下ではなくサブディレクトリの中で管理したい
・protoファイルからprotocコマンドで生成させるpb.goファイルを、protoファイルと同じ階層に置きたい

環境等

go1.16.6
github.com/mwitkow/go-proto-validators v0.3.2
github.com

前提

・以下のフォルダ構造とします
(プロジェクトルート(自分の環境だとgin-studyというフォルダ))
└grpc
 └gin-study.proto

・protoファイルの中身はこんな感じ

syntax = "proto3";

option go_package = "github.com/Tiratom/gin-study/grpc";

import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "github.com/mwitkow/go-proto-validators/validator.proto";

(以下後略)

手順

① ターミナルでecho $GOPATHを実行してGOPATHの値を確認する
Users/【名前】/go って感じの値が返ってくると思います

②validator.protoファイルを用意する
2-1. go-proto-validators/validator.proto at master · mwitkow/go-proto-validators · GitHub からvalidator.protoファイルの中身をコピーする
2-2. /Users/【名前】/go/src/github.com/mwitkow/go-proto-validators/validator.proto の位置になるようにvalidator.protoファイルを作成する
2-3. 2-1でコピーした中身を、2-2で用意したファイルの中にペーストする

※補足
・go-prot-validatorの公式のREADMEの手順でprotocコマンドを実行すると、以下のエラーが発生してしまいました

gin-study.proto:7:1: Import "github.com/mwitkow/go-proto-validators/validator.proto" was not found or had errors.

そこで、こちらを参考にこの2-1〜2-3の手順を実行しています
qiita.com
(記事で言及されているように、注意点があることに注意です・・・注意点を対処できる方法はわかりませんでした・・)

③ 以下コマンドをプロジェクトルートで実行
$ protoc --proto_path=${GOPATH}/src --proto_path=:./grpc --go_out=plugins=grpc:./grpc --go_opt=module=github.com/Tiratom/gin-study/grpc --govalidators_out=paths=source_relative:./grpc ./grpc/gin-study.proto

④ 生成物を確認
gin-study(プロジェクトルート)
└grpc
 ┣gin-study.proto
 ┣gin-study.pb.go
 └gin-study.validator.pb.go

GORMで必要カラムだけを取得したい場合

環境

  • Go1.16.6
  • GORM

やりたいこと

GORMでテーブルからSELECTする際に、全カラムではなく必要なカラムだけを取得したい。

どうやるか

公式ページの以下に書いてある通り。(Advancedのページに書いてあったので最初気づかず悩んだので自分用に整理しています)

gorm.io

具体例

type hoge struct {
    Id int64
}
var i *hoge

t.db.Gdb.Table("hoges").Where("name = ?", "aaa").Find(&i)
// ※hogesテーブルはID以外にもいろんなカラムを持っている前提

// i.Id でSELECT結果のIDカラムを取得可能

Tableでテーブル名を指定しているけど、公式の通りModelで該当テーブルに相当する構造体を指定して取得というのも可能です

メモ

structを作らずに、var i *int64ってやって取得できないものかと思ったけど、Scan called without calling Next というエラーで取得はできなかった。この辺はまた調べないとよくわからないな、、

「Linuxで動かしながら学ぶTCP/IPネットワーク入門」感想

「Linuxで動かしながら学ぶTCP/IPネットワーク入門」という本を読んだのでメモ。
(以下は著者のブログのようです)
blog.amedama.jp

なぜ読んだか

  • Prime Readingで無料だったから
  • ネットワーク系を勉強したいと言ったら友人にお勧めされた「マスタリングTCP/IP」がかなり分厚かったので、読み切る自信がなかったがこれなら読めそうと思ったから
  • ネットワーク系への苦手意識があったから

どんな内容だったか

Ubuntuの仮想環境を構築して、pingでの送信元/送信先IPアドレスの様子や、3ウェイハンドシェイクのフラグの様子を見たりと実際の通信の中身を見ながら、TCP/IPの4つの層をそれぞれ学んでいく。
あくまで入門編なので広く浅くと言ったところ。「DNSって何?もっと知りたい!」とかなったらネットで調べるか、DNSについて取り上げた本で勉強する必要がある。

感想

全般

ネットワークのやりとり内容を観察しながらいろんなプロトコルの動きを見れて、理論だけで終わらず実際の様子を見ることで記憶に定着した気がする。IPv4前提だったので、IPv6の解説をしている本もあればいいなあと思った。
コラムも結構充実してて、確かに気になる!という話題やコラムを読むことでさらに理解が進んだ。

電子書籍での購入だったため分厚さがどのくらいかはわからないが、割と手軽にサクッと読めた。1章分も多過ぎず少な過ぎずで自分の集中力が途切れないちょうどいいくらいでキリよく読み進められた。

その他

『3分間ネットワーク基礎講座』がイラストや話し言葉でとってもわかりやすかったけど実際のやり取りの様子を手を動かして見るというのはないので(僕の記憶)、その部分をこの本が補ってくれるっていう感じでセットものとして読むと良さそうな気がする。また、この『Linuxで動かしながら...』だけだと、「具体的な動きが追えてわかるような気がするんだけどなんかわからない、イメージが掴めない・・・」となるかもしれず、イラスト等でイメージを掴む部分は『3分間...』で補ってく、という形が良いかもしれない。
『3分間...』がGUI, 『Linuxで動かしながら...』がCUIってイメージか。

この3分間ネットワーク基礎講座(シリーズ?)、DNSとかルーティングなどに特化した版もあるので、『Linuxで動かしながら...』を読みつつ気になったところはこのシリーズの該当の本を読むとより理解が進むと思う。

なお『3分間...』はド文系のひよっこ社員だった頃の自分でも読めたが、『Linuxで動かしながら...』はシェルの操作等若干基礎知識・技能がないと読み進めるにはしんどいかもしれない。

環境構築について

  • VirtualBoxを1回も使ったことがない人は勉強がてらVirtualBoxで環境構築するのは良いと思う。
  • VirtualBox使ったことあるし・・という人は、dockerでちゃちゃっと構築してさっさと読み進めたほうが良さそう。
  • 以下はDockerでの環境構築用コマンドだけど、後から思い返しているだけなのでうまくいかないかも
$docker pull ubuntu:latest  
$docker run --privileged -it -d ubuntu:latest 
$docker ps ※動いているコンテナID取得
$docker exec -it コンテナID bash 
(以降は#apt-get updateなど、sudoを消したコマンドを実施)

※wgetでスクリプト取得して動かすときも、「sudo 」は置換して消すなりしたスクリプトにした上で動かす必要があります。

注意事項

  • タブレットで読んでてフォーマットが崩れたのか、本のコマンドでちょこちょこハイフンが表示されていないという現象があった(iPadのKindleアプリ利用)
  • ハイフンが消えていることに気づかずに表示されてるものそのまま打ち込んでエラー、という場合があったので、その場合はコマンドをネットで調べて正しい記述方法を調べるのもまたいい勉強になりそう。

この本をお勧めする人

  • ネットワーク全然よくわからないって人(だけどシェルとかLinux触ったことあるよって人)
  • 基本/応用情報処理技術者試験の勉強をしている人

プロジェクト内の他パッケージを絶対パスでimportする際の僕の勘違い

やろうとしたこと

  • mainパッケージにおいて別ディレクトリに入れている別パッケージを相対パスではなく絶対パスで読み込ませる
  • import "github.com/ユーザー名/レポジトリ名/パッケージ名" の形式でインポートしたい

環境

ディレクトリ構造

.(プロジェクトルート)
├── README.md
├── config
│   └── router.go ←configパッケージ
├── go.mod
├── go.sum
└── main.go  ←mainパッケージ

出てきたエラー

  • 絶対パスでのimportの記載箇所で could not import github.com/Tiratom/gin-study/config (no required module provides package "github.com/Tiratom/gin-study/config")

※Tiratomは僕のGitHubのアカウント名、gin-studyはレポジトリ名です。 main.goにおいて、gin-study/configというインポートは成功することは確認しました。また、router.goをGitHubにプッシュしました。その状態でconfigパッケージを絶対パスでインポートしようとしたのですが、前述のインポートできませんよエラーが発生しました。main.goは以下のように記述していました。

package main

// import "gin-study/config"
import "github.com/Tiratom/gin-study/config"

func main() {
    r := config.GetRouter()
    r.Run(":8080")
}

解決策

Goのpackageを作ろうとしたらgo.modの作り方で困った件 - Qiita

を参考にさせていただきました。

go.modのmoduleの値をもともとはmodule gin-study としていましたが、module github.com/Tiratom/gin-study に修正したところ、無事importでエラーが発生しなくなりました。

補足・メモ

Modules · golang/go Wiki · GitHub において、

A module declares its identity in its go.mod via the module directive, which provides the module path. The import paths for all packages in a module share the module path as a common prefix. The module path and the relative path from the go.mod to a package's directory together determine a package's import path.

という記述があります。 go.modのmoduleに設定した値がインポートパスの共通プレフィックスとなるため、moduleの値がgin-studyにしていたときはインポートがgin-study/configなら成功するけどgithub.com... だと成功しない、という状態になっていたようです。(インポートのパスはGitHubのURLを元につけるのだと勘違いしていました・・・)

また、import "gin-study/config" でも絶対パスのインポートはできていたのですが、import "github.com/..." という形式でのインポートが正だとばかり思っていたので誤った方法でのインポートしかできていないと思い込んでいました。

github.com... のimportはGitHubにプッシュした後でないと行えないと思っていたのですが、上記の理由から別にプッシュしてなくてもimportできるようですね。

多岐にわたって理解が甘く様々な箇所で勘違いをしていました。

複数webhookがあるけど1つしか更新したくない時のaws codepipeline put-webhookで渡すjsonの中身

qiita.com こちらに従ってCodePipelineがGitHubのRelease作成で発火するようになりました。感謝。
1点作業する中で疑問に思ったこととその調査結果メモを備忘録として残しておこうと思います。

疑問に思ったこと

「webhook設定の変更(AWS側)」で行っているaws codepipeline put-webhookにおいて、WebHookが複数存在する時は、全てのwebhook分更新用jsonは用意しないといけないのか?

結論

更新したいwebhook分だけでOK

結論に至るまで

  1. aws codepipeline list-webhooks --region "ap-northeast-1" を実行
{
    "webhooks": [
        {
            "definition": {
                "name": "hoge1--Source--hoge1",
                "targetPipeline": "pipeline1",
                "targetAction": "Source",
                "filters": [
                    {
                        "jsonPath": "$.ref",
                        "matchEquals": "refs/heads/{Branch}"
                    }
                ],
                "authentication": "GITHUB_HMAC",
                "authenticationConfiguration": {
                    "SecretToken": "TOKEN"
                }
            },
            "url": "URL",
            "arn": "ARN",
            "tags": []
        },
        {
            "definition": {
                "name": "hoge2--Source--hoge2",
                "targetPipeline": "pipeline2",
                "targetAction": "Source",
                "filters": [
                    {
                        "jsonPath": "$.ref",
                        "matchEquals": "refs/heads/{Branch}"
                    }
                ],
                "authentication": "GITHUB_HMAC",
                "authenticationConfiguration": {
                    "SecretToken": "TOKEN"
                }
            },
            "url": "URL",
            "arn": "ARN",
            "tags": []
        }
    ]
}

二つwebhookが存在している・・・

  1. 更新するwebhook用のjsonファイルを用意する
    Qiitaの記事を元に
{
  "webhook": {
    "name": "hoge1--Source--hoge1",
    "targetPipeline": "pipeline1",
    "targetAction": "Source",
    "filters": [{ "jsonPath": "$.action", "matchEquals": "published" }],
    "authentication": "GITHUB_HMAC",
    "authenticationConfiguration": {
      "SecretToken": "TOKEN"
    }
  }
}

のようなjsonファイルを用意。
hoge2--Source--hoge2 の方のwebhookは特に変更したくないのでこのjsonファイルには何も記述せず。

  1. webhook-putコマンドを実行
    Qiitaの記事に記載されている通り、aws codepipeline put-webhook --cli-input-json file://webhook_config.json --region "ap-northeast-1" を実行。

  2. 再度aws codepipeline list-webhooks --region "ap-northeast-1" を実行

{
    "webhooks": [
        {
            "definition": {
                "name": "hoge1--Source--hoge1",
                "targetPipeline": "pipeline1",
                "targetAction": "Source",
                "filters": [
                    {
                        "jsonPath": "$.action",
                        "matchEquals": "published"
                    }
                ],
                "authentication": "GITHUB_HMAC",
                "authenticationConfiguration": {
                    "SecretToken": "TOKEN"
                }
            },
            "url": "URL",
            "arn": "ARN",
            "tags": []
        },
        {
            "definition": {
                "name": "hoge2--Source--hoge2",
                "targetPipeline": "pipeline2",
                "targetAction": "Source",
                "filters": [
                    {
                        "jsonPath": "$.ref",
                        "matchEquals": "refs/heads/{Branch}"
                    }
                ],
                "authentication": "GITHUB_HMAC",
                "authenticationConfiguration": {
                    "SecretToken": "TOKEN"
                }
            },
            "url": "URL",
            "arn": "ARN",
            "tags": []
        }
    ]
}

put-pipelineで指定したjsonでは記述していなかったhoge2--Source--hoge2 のwebhookには何も影響なし!

putって言うからjsonファイルの中身が正になって記載していなかったwebhookの情報が消えるのかも?どうしようか・・?と悩んでいましたが、そんな心配は不要でした!