Open KeihakuOh opened 2 months ago
4/14
メモ: package main: main パッケージに属している(main パッケージが Go プログラムのエントリーポイント(開始点)を提供する特別な役割を持っているから必要ある)
import "fmt":他のパッケージから関数、型、変数などを現在のファイルで使用できるようにする
stringは文字列型、string は文字列のポイント型 string型の変数がSの時、valueが'a'とかS&のこの変数のアドレスを示す。 string 型の変数がsの時、valueが'0x14000104030'とか、*sがそのstring型変数のvalueを示す。
関数名最初の文字が小文字の場合:自分が属しているパッケージだけ参照できる 関数名最初の文字が大文字の場合:外のパッケージからも参照できる
構造体(struct)の定義では、各フィールド(属性)に値を必ずしも割り当てる必要はない。初期化時に特定のフィールドを省略した場合、そのフィールドはその型のゼロ値(デフォルト値)で初期化される
fmt.Printlnとlog.Printlnは基本的には同じ機能が、fmt.Println: ユーザーに対する単純なメッセージ出力や、開発中のデータの状態確認に使用。log.Println: システムの動作ログを記録し、エラー情報やその他の実行時情報を含める場合に使用。
オブジェクト指向プログラミング言語:クラスという概念が中心になる。Java、C++、Python、ruby Go言語:構造体を使用してデータと機能をカプセル化するが、メソッドは構造体の外で定義されます。これはクラスベースの言語とは異なる。(Goではメソッドは構造体を引数とした関数を作る。rubyとかはモデルとかのクラス内に書く) Go
4/19
メモ: func PrintInfo(a Animal) { fmt.Println("This animal says", a.Says(), "and has", a.NumberOfLegs(), "legs") } この関数は Animal インターフェースをパラメータとして受け取る。そのため、Dog または Gorilla のどちらかの型のインスタンスが渡されても、Says() と NumberOfLegs() メソッドを呼び出すことができる。
4/24
メモ: defer close(intChan): これにより、チャネルを通じた通信が終了したことが明確になり、リソースが適切に解放される。
module: githubからpackageをもらう場合で使う: import ( "github.com/KeihakuOh/Go-learning/helpers" ) を使うことで、自分でhelpersをを作る必要がない。githubから読みとるから
ここでgo.modについて注意: go.modのmodule名前はこのフォルダがimportされる用の名前 github上からmoduleをimportしたい場合は一旦go get github.com/KeihakuOh/Go-learning/helpers@latestとか(ここによって、go.modにrequireが出てくる、つまりそのモジュール名のファイルはローカルにくる)(4/26)、モジュール名はgithub.com/KeihakuOh/Go-learning/helpers@latestと一致しない可能性ある、なぜならそのリンクはローカルにダウンロード用、モジュール名はそのフォルダのmodファイル内の定義による(5/4)
git pull --no-rebase origin section2-18
git fetch git branch -r git checkout -b origin/
mergeとrebaseの違い: (a). git merge bはcommit一つでbをaを写す。ブランチaのポインタ(aブランチを作った時bブランチのcommitの場所)は変わらない (a). git rebase bはcommitなしでbをaを写す。ブランチaのポインタ(aブランチを作った時bブランチのcommitの場所)は変わる。aブランチを作った場所はbブランチの最新のcommitの場所になる)
cherry pick: 必要なcommitだけをmergeする
4/25
4/26
SOAは企業全体での再利用を目的とし、比較的大規模なサービスを提供します。 マイクロサービスはアプリケーションのスケーラビリティと独立性を高めることを目的とし、小規模で特化したサービスを提供します。
http.HandleFunc は、特定のURLパスに対するリクエストを処理する関数を設定する。例えば;ユーザはlocalhostでアクセスすると、'/'で設定している場合の操作がする
5/2
http.Request http.Request は、クライアントからのHTTPリクエストのすべての情報を含む構造体である。このポインタはリクエストに関連するデータにアクセスするために使用される。重要なフィールドとメソッドは以下の通り:
Method: HTTPメソッド(GET、POST、PUTなど)。 URL: リクエストされたURLの詳細を含む *url.URL オブジェクト。 Header: リクエストヘッダーを含むマップ。 Body: リクエストボディへのアクセスを提供する io.ReadCloser。 Form および PostForm: フォームデータを含む。ParseForm() メソッドを呼び出した後に利用可能。
, = は、fmt.Fprintf から返される二つの値(書き込まれたバイト数とエラー)を無視するために使用されている。, = はなくてもbugは出ない
parsedTemplate, _ := template.ParseFiles("./templates/" + tmpl) /templates/ディレクトリ内にあり、tmpl引数によって指定されたファイル名が使用される
tmplファイルは通常、HTMLファイルの一種が、静的なHTMLとは異なり、Goのテンプレートエンジンで利用するための特別な構文が含まれている。
5/3
メモ: go run main.go main.go のみをコンパイルして実行する go run *.goカレントディレクトリ内の全ての .go ファイルをコンパイルし、実行する。
myproject/ │ ├───src/ │ └───github.com/ │ └───user/ │ └───myproject/ │ └───main.go │ └───go.mod GOPATH を使用する場合、プロジェクトは $GOPATH/src/github.com/user/myproject に配置される。 Go Modules を使用する場合、プロジェクトはどこにでも配置できるが、プロジェクトのルートに go.mod ファイルが必要。
parsedTemplate, _ := template.ParseFiles("./templates/"+tmpl, "./templates/base.layout.tmpl") template.ParseFiles関数が指定された複数のファイルを読み込み、それらを1つのテンプレートとしてマージする
err := parsedTemplate.Execute(w, nil) tmplをHTMLにするってこと
モジュールをインポートした時点で、そのモジュールが利用可能な状態になる! 今のファイルをコンパイルをする時、インポートがある場合は先にインポートするファイルをコンパイルする→お互い相互に(または循環的に)インポートすることはエラーになるよん
link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous" ここでBootstrapフレームワークのスタイル(CSSスタイルの集合)を読み込んでいるけど、まだ適用していない
5/4
メモ: map[string]template.Template: この部分は、マップの型を指定している。string型のキーを持ち、template.Template型の値を持つマップ。*template.Template型は、Go言語のテンプレートを表す型。
30のtc は、プログラム実行時にメモリ内に保存され、テンプレートファイルは、通常ディスク上の特定のディレクトリに物理的に保存されている
31 func createTemplateCache() (map[string]template.Template, error) :この関数は(map[string]template.Template, error) を返すという意味
32 filepath.GlobはGo言語の標準ライブラリpath/filepathに含まれる関数で、特定のパターンに一致するファイルのパスを検索してリストとして返す
ts, err = ts.ParseGlob("./templates/*.layout.tmpl") 既に存在するテンプレートオブジェクトtsに新しく解析したテンプレートを追加する。これにより、ts内には元々のテンプレートに加えて、新たに解析された.layout.tmplファイル群のテンプレートがマージされる。
err = t.Execute(buf, nil) テンプレートオブジェクト: t 出力先: buf(bytes.Buffer型のオブジェクト) err = tmpl.Execute(w, nil) テンプレートオブジェクト: tmpl 出力先: w(通常はHTTPレスポンスを書き込むためのhttp.ResponseWriterオブジェクト) 出力先の違い: bufは出力をメモリ内に保持し、後の処理や送信に使用するために利用される。 wは通常、HTTPレスポンスを直接クライアントに送信するために使用される。
ts, err := template.New(name).ParseFiles(page) parsedTemplate, _ := template.ParseFiles("./templates/" + tmpl) template.New(name)を使用する場合、テンプレートに名前が付けられ、後でこの名前を使ってテンプレートを参照できるようになります。 template.ParseFilesのみを使用する場合、名前なしのテンプレートが作成されます。
log.Fatal 関数は、指定されたメッセージ(この場合は err)をログに出力した後、プログラムを直ちに終了させる。 log.Println は指定されたメッセージをログに出力するだけで、プログラムの実行を停止しない。
section3-35 http.HandleFunc("/", handlers.Repo.Home)、handlersのRepoを引数としてHome関数を呼ぶ
5/5
メモ: pat.New()はルーターを生成する。 muxにはルーティングルールが含まれている。mux 内部では、定義された各ルート(URLパターン)とそれに対応するハンドラー(関数)が連携されている。
5/10
メモ: chi patどちらもHTTPルーティングおよびミドルウェアのフレームワーク pat:早いが機能少ない chi:機能が多い
middleware.Recoverer は chi ミドルウェアの一つで、パニック(プログラムの実行中に予期しないエラーが発生し停止すること)を捕捉し、サーバーのクラッシュを防ぐ役割。このミドルウェアがパニックをキャッチすると、そのエラーをログに記録し、適切にHTTPステータスコード 500(サーバー内部エラー)をクライアントに返す。 NoSurf は、クロスサイトリクエストフォージェリ(CSRF)攻撃から保護するためのミドルウェア。
ミドルウェアはソフトウェアの一つ、常、異なるアプリケーション、サービス、またはソフトウェアコンポーネント間でデータの伝達、管理、通信を仲介するソフトウェアを指す。
ちなみに、データベースはソフトウェア
モジュール:一般に、再利用可能なコードの集まりを指す。これは特定の機能を持つ関数や変数、クラスなどを含むファイルまたは一連のファイルのことを指し、プログラム内で独立した単位として機能する。モジュールは、プログラムの他の部分と独立しているため、必要に応じて他のプロジェクトでも簡単に再利用できる。
ライブラリ:モジュールの集まり。
mux.Use(NoSurf) NoSurf から返された csrfHandler がルーターのミドルウェアスタックに追加される。これにより、mux に設定されたすべてのルート(この例では "/" と "/about")でのリクエスト処理において、csrfHandler による CSRF 保護が自動的に適用される。
mux という変数は、chi.NewRouter() から生成されたもので、chi.Router 型のインスタンス。chi.Router は http.Handler インターフェースを実装している。これは、Go 言語の net/http パッケージに定義されている http.Handler インターフェースを満たしており、そのためには ServeHTTP(w http.ResponseWriter, r *http.Request) メソッドを持っている必要がある
https://maku77.github.io/p/goruwy4/ これわかりやすい
イメージ:chi構造体があって、http.handlerインタフェースがあり、http.handlerインタフェース専用の関数がある。http.handlerインタフェース専用の関数内に処理するときは、http.handlerインタフェース構造体の関数や変数は定義されたchi構造体用の関数や変数に従って実行
5/11
メモ: メソッドレシーバ(Method Receiver) (m Repository): このメソッドが属するレシーバである。RepositoryはRepository型のポインタで、Homeメソッドが呼び出される際のインスタンス(つまり、Repository型のオブジェクト)を指す。このレシーバを通じて、メソッド内からRepository型が持っているフィールドや他のメソッドにアクセスすることができる。ファイル内にすでにある*Repositoryを利用するってこと
m.App.Session.Put(r.Context(), "remote_ip", remoteIP) r.context()からcontext.contextを得た、それによって処理がかわる。のコンテキストには、リクエストのライフサイクルに沿って維持されるべきデータや、キャンセルやデッドライン(タイムアウト)に関連する情報が含まれている。
5/15
5/16
6/7
6/14
rel="stylesheet":このリンクがCSSスタイルシートであることを示す。 type="text/css":リンクされたリソースがCSSファイルであることを示す(最近のブラウザでは省略可能)。
「CSSスタイルシート」は、スタイル情報全般を指す広い意味で使われる "text/css"は.cssのファイルとか
form action="reservation.html" method="post" novalidate class="needs-validation" action="reservation.html" 説明:フォームデータが送信されるURLを指定。この場合、データはreservation.htmlに送信される。
script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script jQueryの読み込み JavaScriptライブラリであり、DOM操作、イベント処理、Ajax通信、アニメーションなどを簡単に行うためのツール
script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script Bootstrap JavaScriptの読み込み div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-toggle="modal" の"modal"はscript src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></scriptによって得たもの
php:PHP(Hypertext Preprocessor)は、サーバーサイドで動作するスクリプト言語で、動的なウェブページの作成やウェブアプリケーションの開発に広く使用されている。PHPはHTMLと組み合わせて使用され、フォームデータの処理、データベース操作、セッション管理など、さまざまなサーバーサイドの機能を実現できる。 クライアント側ではPHPコードは見えず、生成されたHTMLのみが表示されます。 例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PHP Example</title>
</head>
<body>
<?php
echo "Hello, World!";
?>
</body>
</html>
func RenderTemplate(w http.ResponseWriter, tmpl string, td *models.TemplateData) w は http.ResponseWriter インターフェースを実装する具体的なオブジェクト
r *http.Requestでポインタを使用する理由は、http.Requestは多くのフィールドを持つ大きな構造体であるため、コピーには時間とメモリを要するから
AJAX:AJAXを使うことで、ウェブページをリロードせずにサーバーとの通信を行い、ページの一部を動的に更新することができる(以下のfetchのように)
// AJAXリクエストを開始する
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST', // HTTPメソッドを指定
body: formData // フォームデータをリクエストのボディに設定
})
.then(response => response.json()) // レスポンスをJSON形式に変換
.then(data => {
// データをページに表示
const responseDiv = document.getElementById('response');
responseDiv.innerHTML = `
<h3>Form Submitted Successfully</h3>
<p>ID: ${data.id}</p>
`;
})
.catch(error => console.error('Error submitting form:', error)); // エラーをコンソールに表示
});
同期処理: タスクが順番に実行され、前のタスクが完了するまで次のタスクが開始されない。 非同期処理: タスクが同時に実行され、あるタスクが完了するのを待たずに他のタスクを開始できる。 非同期処理でも実行順序がある以下が例
console.log('Start'); // Step 1
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json()) // Step 2 (非同期)
.then(data => {
console.log(data); // Step 4 (非同期)
})
.catch(error => {
console.error('Error:', error); // Step 4 (非同期)
});
console.log('End'); // Step 3
Step 1: "Start" が出力される。 Step 2: fetch が呼び出され、HTTPリクエストが送信されます。リクエストが完了するのを待たずに次のステップに進む(非同期)。 Step 3: "End" が出力される。 Step 4: HTTPリクエストが完了し、レスポンスが受信されると、then ブロックが実行される。ここでレスポンスがJSONに変換され、次の then または catch が実行される(非同期)。
promiseの使い方、また、promiseは以下の三つの状態がある Pending(保留): 初期状態。非同期処理がまだ完了していない状態。 Fulfilled(成功): 非同期処理が成功し、結果が得られた状態。 Rejected(失敗): 非同期処理が失敗し、エラーが発生した状態。
let myPromise = new Promise((resolve, reject) => {
// 非同期処理をシミュレートする
let success = true; // ここで成功条件をシミュレート
if (success) {
resolve('成功時の結果'); // 非同期処理が成功したときに呼び出される
} else {
reject('失敗時の理由'); // 非同期処理が失敗したときに呼び出される
}
});
// Promiseの利用
myPromise.then((result) => {
console.log(result); // "成功時の結果"
}).catch((error) => {
console.error(error); // "失敗時の理由"
});
// データを非同期に取得する関数
function fetchData() {
return new Promise((resolve, reject) => {
// fetch APIを使用してデータを取得
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
if (!response.ok) {
throw new Error('ネットワーク応答が失敗しました');
}
return response.json(); // JSONとしてレスポンスを解析
})
.then(data => {
resolve(data); // 取得したデータをresolveする
})
.catch(error => {
reject(error); // エラーが発生した場合はrejectする
});
});
}
// データ取得の実行
fetchData().then((result) => {
console.log(result); // 取得したデータを出力
}).catch((error) => {
console.error(error); // エラーメッセージを出力
});
let form = document.getElementById("check-availability-form");
let formData = new FormData(form);
formData.append("csrf_token", "{{.CSRFToken}}");
入力内容をキーと値のペアとして保持する構造にする
JavaScriptで構造体
class Car {
constructor(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
displayInfo() {
console.log(`${this.year} ${this.make} ${this.model}`);
}
}
// クラスのインスタンスを作成
let myCar = new Car('Toyota', 'Corolla', 2021);
// 結果を表示
myCar.displayInfo(); // 2021 Toyota Corolla
アロー関数を引数として渡す場合
class Car {
constructor(make, model, year, onDisplay) {
this.make = make;
this.model = model;
this.year = year;
this.onDisplay = onDisplay; // アロー関数をプロパティとして保存
}
displayInfo() {
console.log(`${this.year} ${this.make} ${this.model}`);
if (this.onDisplay) {
this.onDisplay(this.make, this.model); // アロー関数を実行し、引数を渡す
}
}
}
// インスタンスを作成し、アロー関数を引数として渡す
let myCar = new Car('Toyota', 'Corolla', 2021, (make, model) => {
console.log(`This car (${make} ${model}) is now being displayed!`);
});
// メソッドを呼び出して、情報を表示し、アロー関数を実行
myCar.displayInfo();
input type="hidden" name="csrf_token" value="{{.CSRFToken}}" value="{{.CSRFToken}}はTemplateDataから貰う感じ
srv := &http.Server{
Addr: portNumber,
Handler: routes(&app),
}
によってhtmlからのCSRF トークンと比べる
func New(data url.Values) *Form {
return &Form{
data,
errors(map[string][]string{}),
}
}
url.Values 型の data を受け取り、*Form 型のポインタを返す関数
r.ParseForm() GETリクエストの場合、URLのクエリパラメータを解析し、r.Formに格納 POSTリクエストの場合、POSTボディのフォームデータを解析し、r.PostFormに格納 両方のリクエストタイプに対して、r.Formにすべてのフォームデータを格納(つまり、クエリパラメータとPOSTデータの両方が含まれる)
6/18
data := make(map[string]interface{})はハッシュのvalueに任意の型が入れるようにした
var x interface{}
x = 42
fmt.Printf("x is of type %T and value %v\n", x, x)
x = "hello"
fmt.Printf("x is of type %T and value %v\n", x, x)
x = true
fmt.Printf("x is of type %T and value %v\n", x, x)
gob.Register(models.Reservation{}): gobパッケージを使用してmodels.Reservation型を登録する。これによってエンコードおよびデコードができるようになる エンコードおよびデコードができないとこの型のインスタンスをセッションに保存および取得できない
reservation, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation) m.App.Session.Get(r.Context(), "reservation"): m.App.Session.Getは、セッションストアから値を取得するメソッドです。 第一引数にリクエストのコンテキストr.Context()を渡し、第二引数にキー"reservation"を渡して、セッションから該当する値を取得 キャスト部分 . (models.Reservation): セッションから取得した値をmodels.Reservation型にキャストしています。 具体的には、セッションから取得したインターフェース型の値を、具体的な型(ここではmodels.Reservation)に変換する
{{with .Error}}
notify("{{.}}", "error");
{{end}}
{{with .Error}} ... {{end}}: withアクションは、その内部のブロックを実行する前に、指定された値(この場合は.Error)が非空であるかどうかを確認。 .Errorが非空である場合、withブロック内のテンプレートコードが実行される
引数として二つのインタフェースもあり
6/20
go test -cover:どれだけのコードをカバーしているかを確認したいときに使用 PASS coverage: 75.0% of statements ok example.com/project 0.005s
go test はカレントディレクトリのパッケージを検出し、パッケージ内のすべての .go ファイルを確認しコンパイル
go testコマンドの実行: 開発者がgo testコマンドを実行すると、Goのテストツールが起動する。このツールが、パッケージ内のテストファイルをスキャンし、TestMain関数が存在するかどうかを確認する。m.Run()が呼び出され、すべてのテスト関数(この場合はTestExample)が実行される。*testing.M構造体の生成とmへの代入は、Goのテストツールが内部で行う。
var theTests = []struct {
name string
url string
method string
params []postData
expectedStatusCode int
}{
{"home", "/", "GET", []postData{}, http.StatusOK},
}
theTests という変数は、この匿名構造体のスライス
テストの実行順序は、ファイルと関数名のアルファベット順、およびTestMainの存在に基づく。異なるパッケージのテストがある場合、それぞれのパッケージは独立してテストされ、その実行順序は一定ではありませんが、各パッケージ内では上記のルールが適用される
r.Context()はメソッドってこと、flashMessage := app.Session.PopString(r.Context(), "flash")ではsession内の'flash'を取り出す協力をする(補助の役割)r.Context()は直接データを返さないが、セッション管理ライブラリの内部で重要な役割を果たす。
http.handler type Handler interface { ServeHTTP(ResponseWriter, *Request) }
r.context について
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// コンテキストに値を設定する
ctx := context.WithValue(r.Context(), "userID", 12345)
ctx = context.WithValue(ctx, "role", "admin")
ctx = context.WithValue(ctx, "requestID", "abcd-efgh-ijkl")
r = r.WithContext(ctx)
// ハンドラを呼び出す
myHandler(w, r)
})
http.ListenAndServe(":8080", nil)
}
// ハンドラでコンテキストから値を取得する例
func myHandler(w http.ResponseWriter, r *http.Request) {
// コンテキストから値を取得
userID := r.Context().Value("userID").(int)
role := r.Context().Value("role").(string)
requestID := r.Context().Value("requestID").(string)
// 取得した値を使用
fmt.Fprintf(w, "User ID: %d, Role: %s, Request ID: %s\n", userID, role, requestID)
}
テスト関数内で t.Error や t.Errorf が呼び出されると、そのテストは失敗とみなされる。
url.Values : map[string][]string
func (f *Form) Has(field string) bool {
x := f.Get(field)
if x == "" {
return false
}
return true
}
これはFormにメソッドを追加し、F.Hasの時Fというオブジェクトがfに代入
6/21
MySQL、PostgreSQL、SQLITEはデータベースのシステム
JOIN (INNER JOIN) JOIN(通常はINNER JOINとして参照される)は、二つのテーブル間で共通の値を持つ行を結合
SELECT employees.name, departments.name
FROM employees
JOIN departments ON employees.department_id = departments.id;
LEFT JOIN LEFT JOIN(またはLEFT OUTER JOIN)は、左側のテーブル(FROM句で最初に記述されたテーブル)のすべての行と、右側のテーブルの一致する行を結合
SELECT employees.name, departments.name
FROM employees
LEFT JOIN departments ON employees.department_id = departments.id;
従業員がいない部門の場合、従業員名はNULLとして表示
RIGHT JOIN RIGHT JOIN(またはRIGHT OUTER JOIN)は、LEFT JOINの反対で、右側のテーブル(JOIN句で後に記述されたテーブル)のすべての行と、左側のテーブルの一致する行を結合
SELECT employees.name, departments.name
FROM employees
RIGHT JOIN departments ON employees.department_id = departments.id;
従業員がいない部門の場合、従業員名はNULLとして表示
6/25
PATH の動作 初期状態: PATH 環境変数に /opt/homebrew/bin が含まれており、このディレクトリにある soda コマンドが最初に見つかる。 shengbo@WangnoMacBook-Pro ~ % which soda /opt/homebrew/bin/soda PATH を変更した後: export PATH=$HOME/go/bin:$PATH を実行することで、$HOME/go/bin ディレクトリ(ここでは /Users/shengbo/go/bin)が PATH の先頭に追加される。この結果、シェルはまず $HOME/go/bin を検索し、そのディレクトリにある soda コマンドを使用する export PATH=$HOME/go/bin:$PATH shengbo@WangnoMacBook-Pro ~ % which soda /Users/shengbo/go/bin/soda
なぜ二つのところにある? Homebrew を使用してインストールされた soda コマンドは /opt/homebrew/bin にインストールされる。 Goツールチェーン など、別の方法でインストールされた soda コマンドは $HOME/go/bin にインストールされる。 システム全体にインストールされている場合は、一般的に /usr/local/bin や /opt/homebrew/bin などのシステムディレクトリにインストールされる。 ユーザー固有にインストールされた場合は、$HOME/bin や $HOME/go/bin などのユーザーディレクトリにインストールされる。
外部キー 親テーブルの行が削除されたり、更新されたりしたときに、子テーブルの行が適切に処理されることを保証
d.SetMaxOpenConns(maxOpenDbConn) 同時にmaxOpenDbConn個のクエリしかできない
ゴルーチン(Goroutine)は、Go言語における軽量な並行処理の単位。ゴルーチンは、スレッドのように並行して実行されるが、非常に軽量で効率的。ゴルーチンは go キーワードを使用して開始され、バックグラウンドで実行される go say("world") // ゴルーチンを開始 say("hello") // メインゴルーチン
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) context.WithTimeout を使用して、3秒のタイムアウト付きコンテキストを作成する。このコンテキストは、データベース操作が3秒以上かかる場合にキャンセルされる
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
context.WithTimeout を使用して、3秒のタイムアウトを設定。このコンテキストは、データベースクエリが3秒以内に完了しない場合にキャンセル信号を送る。 リソース管理: defer cancel() を使用して、関数の終了時にキャンセル関数が呼び出される。これにより、リソースが解放され、メモリリークが防止される。
exploded := strings.Split(r.RequestURI, "/") roomID, err := strconv.Atoi(exploded[2]) /choose-room/123の場合は123がroomIDにある
ユーザーがフォームを開いたときに、すでに入力フィールドに値が表示されるようにした。また、フォームが送信される際に、入力フィールドが必ず入力されていることを要求
隠しフィールドであり、ユーザーには表示されません。しかし、このフィールドはフォームが送信されるときにサーバーに送信される。ユーザに入力して欲しい場合はtypeを変える
test-repo.go と setup_test.go の両方とも、go test コマンドを実行すると自動的に実行される流れ。
なぜtest-repoとrepoは場合分けて実行されるかとういうと、インタフェースを使っているから。go testの場合はset_upでtest-repoを作ってtest-repoの特有のコードを実行する
goのhttpのhandleはhttp.ResponseWriter, http.Requestのインタフェースが適用したものを受け取って、何も返さない http.requestとしてくるものはhttpの中身(body)とか http.ResponseWriterとしてくるものは特にデータはない、200OKなどを書くためのものだけ
handleはインタフェースhttp.ResponseWriterとインタフェースhttp.Requestの関数。handleをhandlefuncタイプにすると、handlefunc特有のserverhttpが使える
コンテナ:docker 軽量で迅速なデプロイが可能。 他のコンテナと同じホストで実行可能。 必要な依存関係だけを含むため、効率的にリソースを使用。 vm: VirtualBoxを使用して、Ubuntuをインストールする仮想マシンを作成。 完全に独立したオペレーティングシステム環境を提供。 高いセキュリティと安定性。 異なるOSやソフトウェア構成でのテストが可能。
プロセスは独立(メモリを共有しない) スレッドはプロセス内のもの(メモリを共有する) メモリを共有しない場合は他のメモリの値見れないってこと
MailHog 送信されたメールを確認するためのWebインターフェース(通常ポート8025)を提供
CSR(クライアントサイドレンダリング)とSSR(サーバーサイドレンダリング) CSR:初回読み込みでは基本的なHTMLのみが送信され、JavaScriptが実行されることで完全なページが生成される。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSR Example</title>
<script src="main.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
ブラウザが main.js ファイルをサーバーにリクエストし、サーバーはリクエストを受け取り、main.js ファイルを返す。ブラウザはこのJavaScriptファイルをダウンロードする。 SSR:サーバーサイドレンダリングでは、ウェブページのレンダリングがサーバーで行われ、完全なHTMLがクライアントに送信される
func listenformail() {
go func() {
for {
msg := <-app.MailChan // チャネルからメッセージを受信
// 受信したメッセージを処理するコードをここに追加できます
fmt.Println("Received message:", msg)
}
}()
}
listenformail関数では、無名関数を新しいゴルーチン(並行処理)として起動し、その中で無限ループを実行する
sudo chmod -R 700 /path/to/directory: オーナーだけが読み取り、書き込み、実行可能。グループおよびその他のユーザーはアクセス不可。 sudo chmod -R 777 /path/to/directory: オーナー、グループ、およびその他のユーザー全員が読み取り、書き込み、実行可能。セキュリティリスクが高い設定。
{{with .Form.Errors.Get "first_name"}}
{{end}} .Form.Errors.Get "first_name"の時だけ実行するやつ、if文近いイメージ
err := m.DB.QueryRowContext(ctx, stmt,
res.FirstName,
res.LastName,
res.Email,
res.Phone,
res.StartDate,
res.EndDate,
res.RoomID,
time.Now(),
time.Now(),
).Scan(&newID)
Scanメソッドは、SQLクエリの結果を受け取り、その結果を指定した変数に割り当てるために使用される。この場合、新しく挿入された予約のIDがnewIDに格納される
[x] section 17 (6/31)
_ = m.App.Session.Destroy(r.context())の場合はm.Appの全ユーザのSessionがを消すかどうかはrの中身自体 func (m Repository) Home(w http.ResponseWriter, r http.Request) のように定義されたメソッドは、Repository 型のインスタンスを持っている限り、どのファイルからでも適切なタイミングで呼び出すことができる