04 May 2023
方法如下:
<a href="某個網址" target="_blank" rel="noreferrer noopenner">
New link
</a>
根據 google chrome 官方說明:
rel="noopener"
prevents the new page from being able to access the window.opener property and ensures it runs in a separate process.
rel="noreferrer"
has the same effect but also prevents the Referer header from being sent to the new page. See Link type “noreferrer”.
簡而言之,後面的 rel="noreferrer noopenner"
是安全性考量,避免新開的頁面如果是 malicious page 會影響到原本的頁面。不過新版的瀏覽器目前都默認 target="_blank"
link 使用 rel=noopener
。
Reference
Links to cross-origin destinations are unsafe
target=”_blank” 的安全性風險
03 May 2023
在 Route 的過程中,發現一個問題,那就是如何在跳轉到 /user
這個 link 的同時,透過 /user/:userid
這種方式將想傳遞的內容傳遞到 component 內呢?找到的方法如下:
- 定義 Route,後面的
<User />
是要路由過去的 component,也就是需要取得 userid 的頁面
<Route path="user/:userid" element={<User />} />
- 頁面跳轉的 Link,userid 是某個 dynamic 的變數,像如果 userid 是 1 的話,等同
<Link href="/user/1" />
<Link href={"/user/"+ userid} />
- 在目標頁面(component),也就是
<User />
內取得id
import { useParams } from "react-router-dom";
let { userid } = useParams();
Reference
React-Router v6 教学(附demo)
React-Router doc
02 May 2023
控制 Goroutine 的方式有 Waitgroup 和 Context,前面有講過 Waitgroup 簡單來說是可以指定一個數量,等到這個數量的 job 都執行完了之後再繼續執行主程式。
Context 的話,goroutine 內可能又有多個 goroutine,背景又有別的 goroutine,取消就會變得很麻煩,這就是 Context 常見的使用場景,在複雜的 goroutine 場景進行取消非常好用,又可以理解成:多個或有上下層關係的 goroutine 同步請求、處理請求、取消。
建立 Context 的方法:
context.Backgroud()
, 較常使用
context.TODO()
With 函數(使用時需要從父 Context 衍生):
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context
WithTimeout,超時取消範例:
package main
import (
"context"
"fmt"
"time"
)
func main() {
HttpHandler()
}
func HttpHandler() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
// cancel 其實沒被使用到 context 就結束了,但必須 defer cancel() 來避免 context leak
defer cancel()
deal(ctx)
}
func deal(ctx context.Context) {
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
select {
case <-ctx.Done(): // 三秒後context被關閉,執行此處
fmt.Println(ctx.Err())
return
default: // 前三秒時
fmt.Printf("deal time is %d\n", i)
}
}
}
WithCancel,取消範例:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go Talk(ctx)
time.Sleep(10 * time.Second)
cancel() // 十秒後閉嘴
time.Sleep(1 * time.Second)
}
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go Talk(ctx)
time.Sleep(10 * time.Second)
cancel()
time.Sleep(1 * time.Second)
}
func Talk(ctx context.Context) {
for range time.Tick(time.Second) {
select {
case <-ctx.Done():
fmt.Println("我要閉嘴了")
return
default:
fmt.Println("balabalabalabala")
}
}
}
Reference
【Go语言】小白也能看懂的context包详解:从入门到精通
用 10 分鐘了解 Go 語言 context package 使用場景及介紹
27 Apr 2023
資料庫提交數據的三種類型:
顯式提交 (Explicit Commit)
用 COMMIT
命令完成提交,例如:
select * from dept;
commit;
隱式提交 (Implicit Commit)
運行某些指令之後資料庫自動完成,不需要再做 COMMIT
,例如:
CREATE TABLE Persons (
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);
隱式提交的指令有:CREATE TABLE
、DROP TABLE
等,這些指令各自被視作單一的 transaction,因此執行完畢做 ROLLBACK
不會有用。更多可以參考 Statements That Cause an Implicit Commit。
自動提交 (Autocommit)
如果 autocommit mode 開啟的話,每一個 SQL statement 都將被視作單一的 transaction,不需要 COMMIT
,會自動完成提交。MySQL 默認 autocommit mode 開啟。
可以用 SELECT @@autocommit
指令確認 autocommit mode 是否開啟,是的話值為 1。
Reference
autocommit, Commit, and Rollback
MYSQL的COMMIT和ROLLBACK使用讲解
26 Apr 2023
常見的 Structured Query Language 指令有 Create, Drop, Insert 等,而這些指令又可以細分為幾個種類:
DDL (Data Definition Language)
這個種類的指令大多用來建立、變更、刪除資料庫物件的結構或 schema,例如:
- CREATE
- DROP
- ALTAR
- TRUNCATE
- RENAME
DQL – Data Query Language
一言以蔽之,用來查詢資料庫的資料,例如 SELECT。
DML – Data Manipulation Language
操作和修改資料庫中的資料,常見的有:
- INSERT
- UPDATE
- DELETE
DCL – Data Control Language
與權限、授權、許可相關的指令,例如:
- GRANT
- REVOKE
TCL – Transaction Control Language
與控制、管理事務(Transaction)相關,例如:
- BEGIN
- COMMIT
- ROLLBACK
Reference