Slide 1

Slide 1 text

id:susisu / 2025-08-23 Kyoto.ͳΜ͔ #7 GoͰݴ͏ͱ͜ΖͷΞϨ͸ TypeScriptͰݴ͏ͱίϨ

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

࠷ۙॻ͍ͨTypeScript

Slide 5

Slide 5 text

࠷ۙॻ͍ͨTypeScriptʢ̍ʣ • ಠཱͳ worker Λෳ਺ىಈͯ͠δϣϒΛॲཧͯ͠΋Β͏ main workerα workerβ workerγ ⋮ δϣϒΛΤϯΩϡʔ

Slide 6

Slide 6 text

࠷ۙॻ͍ͨTypeScriptʢ̍ʣ • main ͷऴྃ࣌ʹ͸ worker ΋ॲཧதͷδϣϒ͕ऴΘΓ࣍ୈఀࢭͤ͞Δ main workerα workerβ workerγ ⋮ ܬͷޫ SIGTERM

Slide 7

Slide 7 text

• API αʔόʔ͔ΒͷετϦʔϜΛӬଓԽͭͭ͠ΫϥΠΞϯτʹ΋ฦ͢ app server ࠷ۙॻ͍ͨTypeScriptʢ̎ʣ req handler worker API server DB client ϦΫΤετ ϦΫΤετ ىಈ

Slide 8

Slide 8 text

• API αʔόʔ͔ΒͷετϦʔϜΛӬଓԽͭͭ͠ΫϥΠΞϯτʹ΋ฦ͢ app server ࠷ۙॻ͍ͨTypeScriptʢ̎ʣ req handler worker API server DB client Ϩεϙϯε Ϩεϙϯε ӬଓԽ Ϩεϙϯε

Slide 9

Slide 9 text

• ΫϥΠΞϯτ్͕தͰ੾அ͞Εͯ΋ӬଓԽͳͲͷॲཧ͸ଓ͚Δ app server ࠷ۙॻ͍ͨTypeScriptʢ̎ʣ req handler worker API server DB client X X ӬଓԽ Ϩεϙϯε

Slide 10

Slide 10 text

app server req handler worker API server DB client X X ӬଓԽ Ϩεϙϯε main workerα workerβ workerγ ⋮ ܬͷޫ SIGTERM Go͔ʁ

Slide 11

Slide 11 text

͍͔ʹ΋GoͰॻ͖ͦ͏ • ಠཱͨ͠ worker → goroutine • தஅγάφϧͷ఻೻ → context • worker ؒͷσʔλૹड৴ → channel

Slide 12

Slide 12 text

TypeScriptͰ͸Ͳ͏͢Δʁ • ಠཱͨ͠ worker → ? • தஅγάφϧͷ఻೻ → ? • worker ؒͷσʔλૹड৴ → ?

Slide 13

Slide 13 text

goroutine • ܰྔεϨου, ฒߦɾฒྻॲཧ go func() { time.Sleep(time.Second) fmt.Println("Pong") }() fmt.Println("Ping") // Ping // (1s) // Pong

Slide 14

Slide 14 text

goroutine → async function • ϚϧνεϨου͕ཉ͍͠ͳΒ Web Workers ͳͲ͕ඞཁ͚ͩͲ (async function() { await setTimeout(1000); console.log("Pong"); })(); console.log("Ping"); // Ping // (1s) // Pong

Slide 15

Slide 15 text

context • தஅγάφϧͷ఻೻ ctx, cancel := context.WithCancel(context.Background()) startWorker(ctx) // ... cancel()

Slide 16

Slide 16 text

context → AbortController • DOM Standard Ͱఆٛ͞Ε͍ͯΔ AbortController ͕࢖͑Δ const ac = new AbortController(); startWorker(ac.signal); // ... ac.abort();

Slide 17

Slide 17 text

context • ϦΫΤετείʔϓͷ஋ͷ఻೻ʹ΋࢖ΘΕΔ ctx := context.WithValue(context.Background(), "requestId", "c0ffee") handler(ctx) // handler: ctx.Value("requestId") // = "c0ffee"

Slide 18

Slide 18 text

context → ? • ୯ʹΦϒδΣΫτΛҾ਺Ͱ౉͢ͷ͕جຊ͚ͩͲ... const ctx = { requestId: "c0ffee" }; handler(ctx); // handler: ctx.requestId; // = "c0ffee"

Slide 19

Slide 19 text

context → AsyncLocalStorage • Ҿ਺Λ౉͢ͷ͕೉͍࣌͠͸ AsyncLocalStorage (ඇඪ४) ͕ศར͔΋ const storage = new AsyncLocalStorage<{ requestId: string }>(); const ctx = { requestId: "c0ffee" }; storage.run(ctx, () => { handler(); }); // handler: storage.getStore()?.requestId; // = "c0ffee"

Slide 20

Slide 20 text

channel • goroutine ؒͷσʔλͷૹड৴ c := make(chan int) go func() { for n := 0; n < 10; n++ { c <- n } close(c) }() for n := range c { fmt.Println(n) } // 0, 1, 2, ..., 9

Slide 21

Slide 21 text

channel → Streams • Streams API ͰࣅͨΑ͏ͳ͜ͱ͕Ͱ͖·͢ const { readable, writable } = new TransformStream(); (async function() { const writer = writable.getWriter(); for (let n = 0; n < 10; n++) { await writer.write(n); } await writer.close(); })(); for await (const n of readable) { console.log(n); } // 0, 1, 2, ..., 9

Slide 22

Slide 22 text

channel • ͪͳΈʹऴྃΛ଴͚ͭͩͳΒ c := make(chan struct{}) go func() { // ... close(c) }() // ... <-c

Slide 23

Slide 23 text

channel → await • await ͰΑ͍Ͱ͢Ͷ const promise = (async function() { // ... })(); // ... await promise;

Slide 24

Slide 24 text

·ͱΊʢ̍ʣ • Go Ͱݴ͏ͱ͜ΖͷΞϨ͸ TypeScript Ͱݴ͏ͱίϨ • goroutine → async function • context → AbortController, AsyncLocalStorage • channel → Streams ͳͲ

Slide 25

Slide 25 text

·ͱΊʢ̎ʣ • TypeScript Λॻ͍͍ͯͯ΋ৗʹ TypeScript Ͱߟ͍͑ͯΔΘ͚Ͱ͸ͳ͍ • ࣮ࡍ͸ߟ͑΍͍͢ݴޠ΍ϝϯλϧϞσϧ΋࢖ͬͯߟ͍͑ͯΔ • ࠓճ͸ͨ·ͨ· Go ͬΆ͔ͬͨ • ৭ʑ஌͍ͬͯΔͱศར