Go言語 2025 - バックエンド開発の主流言語へ

2026.01.12

公式ドキュメント

Go言語がバックエンド開発の主流に

2025年、Go言語(Golang)はバックエンド開発において確固たる地位を確立しました。シンプルな構文、優れた並行処理機能、そして高速なコンパイル速度により、スタートアップからエンタープライズまで幅広い企業がGoを採用しています。特にクラウドネイティブアプリケーションとマイクロサービスアーキテクチャにおいて、Goは事実上の標準言語となりつつあります。

Go 1.22/1.23の新機能

Go 1.22(2024年2月リリース)

Go 1.22では、開発者体験を大幅に向上させる重要な変更が導入されました。

forループ変数のセマンティクス変更

package main

import (
 "fmt"
 "sync"
)

func main() {
 var wg sync.WaitGroup
 values := []int{1, 2, 3, 4, 5}

 for _, v := range values {
 wg.Add(1)
 // Go 1.22以降: 各イテレーションで新しい変数が作成される
 go func() {
 defer wg.Done()
 fmt.Println(v) // 期待通りの値が出力される
 }()
 }
 wg.Wait()
}

整数範囲のforループ

// Go 1.22から整数でのrangeが可能に
for i := range 10 {
 fmt.Println(i) // 0, 1, 2, ..., 9
}

// 従来の書き方
for i := 0; i < 10; i++ {
 fmt.Println(i)
}

Go 1.23(2024年8月リリース)

Go 1.23では待望のイテレーター機能が正式導入されました。

range over func(イテレーター)

package main

import (
 "fmt"
 "iter"
)

// カスタムイテレーターの定義
func Fibonacci(n int) iter.Seq[int] {
 return func(yield func(int) bool) {
 a, b := 0, 1
 for i := 0; i < n; i++ {
 if !yield(a) {
 return
 }
 a, b = b, a+b
 }
 }
}

func main() {
 // イテレーターを使用
 for v := range Fibonacci(10) {
 fmt.Println(v) // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
 }
}

slices/mapsパッケージの拡張

import (
 "slices"
 "maps"
)

// slicesパッケージの新機能
numbers := []int{1, 2, 3, 4, 5}

// Chunk: スライスを分割
for chunk := range slices.Chunk(numbers, 2) {
 fmt.Println(chunk) // [1 2], [3 4], [5]
}

// Backward: 逆順イテレーション
for i, v := range slices.Backward(numbers) {
 fmt.Printf("index: %d, value: %d\n", i, v)
}

// mapsパッケージの新機能
m := map[string]int{"go": 1, "rust": 2, "java": 3}

for k := range maps.Keys(m) {
 fmt.Println(k)
}

for v := range maps.Values(m) {
 fmt.Println(v)
}

uniqueパッケージ

import "unique"

// 文字列の正規化(インターニング)
h1 := unique.Make("hello")
h2 := unique.Make("hello")

fmt.Println(h1 == h2) // true(同じハンドル)
fmt.Println(h1.Value()) // "hello"

採用企業とユースケース

クラウドネイティブ基盤

Goはクラウドネイティブエコシステムの中核を担っています。

# 主要なGoで構築されたプロジェクト
cloud_native_projects:
 container_orchestration:
 - name: Kubernetes
 description: コンテナオーケストレーションのデファクトスタンダード
 github_stars: 110000+

 - name: Docker
 description: コンテナ技術の基盤
 github_stars: 70000+

 service_mesh:
 - name: Istio
 description: サービスメッシュプラットフォーム
 github_stars: 35000+

 - name: Linkerd
 description: 軽量サービスメッシュ
 github_stars: 10000+

 observability:
 - name: Prometheus
 description: メトリクス収集・監視システム
 github_stars: 55000+

 - name: Grafana Loki
 description: ログ集約システム
 github_stars: 23000+

 - name: Jaeger
 description: 分散トレーシング
 github_stars: 20000+

 infrastructure:
 - name: Terraform
 description: Infrastructure as Code
 github_stars: 42000+

 - name: etcd
 description: 分散キーバリューストア
 github_stars: 49800+

企業での採用事例

企業用途規模
GoogleYouTube、Googleクラウド基盤数十億リクエスト/日
Uberマイクロサービス、地理情報処理数百万トリップ/日
Twitchビデオストリーミング基盤数百万同時視聴者
Dropboxストレージ同期システム数億ファイル同期
NetflixカオスエンジニアリングツールグローバルCDN
Cloudflareエッジコンピューティング数十億リクエスト/日
Mercariマイクロサービス基盤国内最大級フリマ
LINEメッセージング基盤数億メッセージ/日

日本企業での採用拡大

japanese_companies:
 fintech:
 - name: PayPay
 use_case: 決済処理基盤
 scale: 月間決済数億件

 - name: Moneytree
 use_case: 金融データ集約

 ecommerce:
 - name: Mercari
 use_case: マイクロサービス
 migration: Pythonから移行

 - name: ZOZO
 use_case: 商品検索・レコメンド

 media:
 - name: AbemaTV
 use_case: 動画配信基盤

 - name: DeNA
 use_case: ゲームバックエンド

Go vs Rust vs Java 比較

パフォーマンス比較

performance_benchmark:
 http_server_throughput:
 test: "JSON シリアライズ + HTTP レスポンス"
 requests_per_second:
 go_fasthttp: 850000
 rust_actix: 920000
 java_netty: 620000
 go_std: 580000
 java_spring: 180000

 memory_usage:
 test: "10000 並行接続時のメモリ使用量"
 memory_mb:
 go: 45
 rust: 32
 java: 380

 startup_time:
 test: "アプリケーション起動時間"
 milliseconds:
 go: 15
 rust: 12
 java_spring: 3500
 java_graalvm_native: 45

 compile_time:
 test: "中規模プロジェクト(10万行)"
 seconds:
 go: 8
 rust: 180
 java: 25

言語特性比較

特性GoRustJava
学習曲線緩やか急峻中程度
メモリ安全性GC所有権システムGC
並行処理モデルgoroutine/channelasync/await + Send/SyncThread/Virtual Thread
コンパイル速度非常に高速遅い中程度
バイナリサイズ極小大(JVM必要)
エコシステム充実成長中非常に充実
エンタープライズ実績非常に高

ユースケース別推奨

use_case_recommendations:
 # Goが最適なケース
 go_recommended:
 - マイクロサービス開発
 - API サーバー
 - DevOps ツール
 - CLI アプリケーション
 - クラウドネイティブ開発
 - 高並行処理システム

 # Rustが最適なケース
 rust_recommended:
 - システムプログラミング
 - WebAssembly
 - 組み込みシステム
 - ゲームエンジン
 - 最大パフォーマンスが必要な場合

 # Javaが最適なケース
 java_recommended:
 - エンタープライズアプリケーション
 - Android開発
 - 大規模チーム開発
 - 既存Javaエコシステム活用

実践的なコード例

高性能HTTPサーバー

package main

import (
 "context"
 "encoding/json"
 "log"
 "net/http"
 "os"
 "os/signal"
 "syscall"
 "time"
)

type User struct {
 ID int64 `json:"id"`
 Name string `json:"name"`
 Email string `json:"email"`
 CreatedAt time.Time `json:"created_at"`
}

type Response struct {
 Success bool `json:"success"`
 Data interface{} `json:"data,omitempty"`
 Error string `json:"error,omitempty"`
}

func main() {
 mux := http.NewServeMux()

 // ルーティング設定
 mux.HandleFunc("GET /health", healthHandler)
 mux.HandleFunc("GET /api/users", getUsersHandler)
 mux.HandleFunc("GET /api/users/{id}", getUserHandler)
 mux.HandleFunc("POST /api/users", createUserHandler)

 // ミドルウェアの適用
 handler := loggingMiddleware(corsMiddleware(mux))

 server := &http.Server{
 Addr: ":8080",
 Handler: handler,
 ReadTimeout: 15 * time.Second,
 WriteTimeout: 15 * time.Second,
 IdleTimeout: 60 * time.Second,
 }

 // グレースフルシャットダウン
 go func() {
 log.Printf("Server starting on %s", server.Addr)
 if err := server.ListenAndServe(); err != http.ErrServerClosed {
 log.Fatalf("Server error: %v", err)
 }
 }()

 quit := make(chan os.Signal, 1)
 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
 <-quit

 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 defer cancel()

 if err := server.Shutdown(ctx); err != nil {
 log.Fatalf("Server shutdown error: %v", err)
 }
 log.Println("Server stopped gracefully")
}

func loggingMiddleware(next http.Handler) http.Handler {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 start := time.Now()
 next.ServeHTTP(w, r)
 log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
 })
}

func corsMiddleware(next http.Handler) http.Handler {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 w.Header().Set("Access-Control-Allow-Origin", "*")
 w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
 w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
 if r.Method == "OPTIONS" {
 w.WriteHeader(http.StatusOK)
 return
 }
 next.ServeHTTP(w, r)
 })
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
 json.NewEncoder(w).Encode(Response{Success: true, Data: "OK"})
}

func getUsersHandler(w http.ResponseWriter, r *http.Request) {
 users := []User{
 {ID: 1, Name: "Alice", Email: "alice@example.com", CreatedAt: time.Now()},
 {ID: 2, Name: "Bob", Email: "bob@example.com", CreatedAt: time.Now()},
 }
 w.Header().Set("Content-Type", "application/json")
 json.NewEncoder(w).Encode(Response{Success: true, Data: users})
}

func getUserHandler(w http.ResponseWriter, r *http.Request) {
 id := r.PathValue("id")
 user := User{ID: 1, Name: "User " + id, Email: "user@example.com", CreatedAt: time.Now()}
 w.Header().Set("Content-Type", "application/json")
 json.NewEncoder(w).Encode(Response{Success: true, Data: user})
}

func createUserHandler(w http.ResponseWriter, r *http.Request) {
 var user User
 if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
 w.WriteHeader(http.StatusBadRequest)
 json.NewEncoder(w).Encode(Response{Success: false, Error: err.Error()})
 return
 }
 user.ID = time.Now().UnixNano()
 user.CreatedAt = time.Now()
 w.Header().Set("Content-Type", "application/json")
 w.WriteHeader(http.StatusCreated)
 json.NewEncoder(w).Encode(Response{Success: true, Data: user})
}

ポイント: goroutineとchannelの組み合わせは、ワーカープール・ファンアウト/ファンイン・パイプラインなどの並行処理パターンを直感的に実装できます

goroutineとchannelによる並行処理

package main

import (
 "context"
 "fmt"
 "sync"
 "time"
)

// ワーカープールパターン
func WorkerPool(ctx context.Context, jobs <-chan int, results chan<- int, numWorkers int) {
 var wg sync.WaitGroup

 for i := 0; i < numWorkers; i++ {
 wg.Add(1)
 go func(workerID int) {
 defer wg.Done()
 for {
 select {
 case job, ok := <-jobs:
 if !ok {
 return
 }
 // 処理をシミュレート
 time.Sleep(100 * time.Millisecond)
 results <- job * 2
 case <-ctx.Done():
 return
 }
 }
 }(i)
 }

 wg.Wait()
 close(results)
}

// ファンアウト・ファンインパターン
func FanOutFanIn(input <-chan int, numWorkers int) <-chan int {
 // ファンアウト: 複数のワーカーに分散
 workers := make([]<-chan int, numWorkers)
 for i := 0; i < numWorkers; i++ {
 workers[i] = worker(input)
 }

 // ファンイン: 結果を統合
 return merge(workers...)
}

func worker(input <-chan int) <-chan int {
 output := make(chan int)
 go func() {
 defer close(output)
 for n := range input {
 output <- process(n)
 }
 }()
 return output
}

func process(n int) int {
 time.Sleep(50 * time.Millisecond)
 return n * n
}

func merge(channels ...<-chan int) <-chan int {
 var wg sync.WaitGroup
 merged := make(chan int)

 output := func(ch <-chan int) {
 defer wg.Done()
 for n := range ch {
 merged <- n
 }
 }

 wg.Add(len(channels))
 for _, ch := range channels {
 go output(ch)
 }

 go func() {
 wg.Wait()
 close(merged)
 }()

 return merged
}

// パイプラインパターン
func Pipeline() {
 // ステージ1: 数値生成
 gen := func(nums ...int) <-chan int {
 out := make(chan int)
 go func() {
 defer close(out)
 for _, n := range nums {
 out <- n
 }
 }()
 return out
 }

 // ステージ2: 2乗
 sq := func(in <-chan int) <-chan int {
 out := make(chan int)
 go func() {
 defer close(out)
 for n := range in {
 out <- n * n
 }
 }()
 return out
 }

 // ステージ3: フィルタリング
 filter := func(in <-chan int, predicate func(int) bool) <-chan int {
 out := make(chan int)
 go func() {
 defer close(out)
 for n := range in {
 if predicate(n) {
 out <- n
 }
 }
 }()
 return out
 }

 // パイプラインの構築
 numbers := gen(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
 squared := sq(numbers)
 result := filter(squared, func(n int) bool { return n > 25 })

 for n := range result {
 fmt.Println(n) // 36, 49, 64, 81, 100
 }
}

// セマフォによる並行数制限
type Semaphore struct {
 sem chan struct{}
}

func NewSemaphore(maxConcurrency int) *Semaphore {
 return &Semaphore{
 sem: make(chan struct{}, maxConcurrency),
 }
}

func (s *Semaphore) Acquire() {
 s.sem <- struct{}{}
}

func (s *Semaphore) Release() {
 <-s.sem
}

func main() {
 // ワーカープールの使用例
 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 defer cancel()

 jobs := make(chan int, 100)
 results := make(chan int, 100)

 // ジョブを投入
 go func() {
 for i := 1; i <= 50; i++ {
 jobs <- i
 }
 close(jobs)
 }()

 // ワーカープール起動(5ワーカー)
 go WorkerPool(ctx, jobs, results, 5)

 // 結果を収集
 for result := range results {
 fmt.Printf("Result: %d\n", result)
 }

 // パイプラインの実行
 fmt.Println("\n--- Pipeline ---")
 Pipeline()
}

実践メモ: Go 1.18で導入されたGenericsを活用すると、Map/Filter/Reduceなどの汎用的なスライス操作を型安全に実装できます

Genericsを活用したユーティリティ

package main

import (
 "cmp"
 "fmt"
 "slices"
)

// ジェネリックなResult型
type Result[T any] struct {
 value T
 err error
}

func Ok[T any](value T) Result[T] {
 return Result[T]{value: value}
}

func Err[T any](err error) Result[T] {
 return Result[T]{err: err}
}

func (r Result[T]) Unwrap() (T, error) {
 return r.value, r.err
}

func (r Result[T]) UnwrapOr(defaultValue T) T {
 if r.err != nil {
 return defaultValue
 }
 return r.value
}

func (r Result[T]) Map(fn func(T) T) Result[T] {
 if r.err != nil {
 return r
 }
 return Ok(fn(r.value))
}

// ジェネリックなスライス操作
func Map[T, U any](slice []T, fn func(T) U) []U {
 result := make([]U, len(slice))
 for i, v := range slice {
 result[i] = fn(v)
 }
 return result
}

func Filter[T any](slice []T, predicate func(T) bool) []T {
 result := make([]T, 0)
 for _, v := range slice {
 if predicate(v) {
 result = append(result, v)
 }
 }
 return result
}

func Reduce[T, U any](slice []T, initial U, fn func(U, T) U) U {
 result := initial
 for _, v := range slice {
 result = fn(result, v)
 }
 return result
}

// ジェネリックなキャッシュ
type Cache[K comparable, V any] struct {
 data map[K]V
}

func NewCache[K comparable, V any]() *Cache[K, V] {
 return &Cache[K, V]{
 data: make(map[K]V),
 }
}

func (c *Cache[K, V]) Get(key K) (V, bool) {
 v, ok := c.data[key]
 return v, ok
}

func (c *Cache[K, V]) Set(key K, value V) {
 c.data[key] = value
}

func (c *Cache[K, V]) Delete(key K) {
 delete(c.data, key)
}

// 順序付きマップ
type OrderedMap[K cmp.Ordered, V any] struct {
 keys []K
 values map[K]V
}

func NewOrderedMap[K cmp.Ordered, V any]() *OrderedMap[K, V] {
 return &OrderedMap[K, V]{
 keys: make([]K, 0),
 values: make(map[K]V),
 }
}

func (m *OrderedMap[K, V]) Set(key K, value V) {
 if _, exists := m.values[key]; !exists {
 m.keys = append(m.keys, key)
 slices.Sort(m.keys)
 }
 m.values[key] = value
}

func (m *OrderedMap[K, V]) Range(fn func(K, V) bool) {
 for _, k := range m.keys {
 if !fn(k, m.values[k]) {
 break
 }
 }
}

func main() {
 // Map, Filter, Reduce の使用
 numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

 doubled := Map(numbers, func(n int) int { return n * 2 })
 fmt.Println("Doubled:", doubled)

 evens := Filter(numbers, func(n int) bool { return n%2 == 0 })
 fmt.Println("Evens:", evens)

 sum := Reduce(numbers, 0, func(acc, n int) int { return acc + n })
 fmt.Println("Sum:", sum)

 // Cacheの使用
 cache := NewCache[string, int]()
 cache.Set("users", 100)
 cache.Set("posts", 500)

 if v, ok := cache.Get("users"); ok {
 fmt.Printf("Users count: %d\n", v)
 }

 // Result型の使用
 result := Ok(42).Map(func(n int) int { return n * 2 })
 value := result.UnwrapOr(0)
 fmt.Printf("Result value: %d\n", value)
}

パフォーマンスベンチマーク

Goの性能特性

benchmark_results:
 json_serialization:
 test: "10000件のJSON シリアライズ/デシリアライズ"
 results:
 go_standard: 45ms
 go_jsoniter: 28ms
 go_sonic: 18ms
 rust_serde: 15ms
 java_jackson: 52ms

 http_latency:
 test: "99パーセンタイル応答時間(10000 req/s)"
 results:
 go_net_http: 2.1ms
 go_fasthttp: 0.8ms
 rust_actix: 0.6ms
 java_spring: 8.5ms
 java_quarkus: 3.2ms

 memory_allocation:
 test: "100万リクエスト処理後のヒープサイズ"
 results:
 go: 120MB
 rust: 45MB
 java: 850MB
 java_graalvm: 180MB

 garbage_collection:
 test: "GCポーズ時間(P99)"
 results:
 go_1_23: 0.5ms
 go_1_21: 1.2ms
 java_g1gc: 15ms
 java_zgc: 1ms

ベンチマークコード

package main

import (
 "encoding/json"
 "testing"
)

type BenchData struct {
 ID int64 `json:"id"`
 Name string `json:"name"`
 Tags []string `json:"tags"`
 Score float64 `json:"score"`
 Active bool `json:"active"`
}

func BenchmarkJSONMarshal(b *testing.B) {
 data := BenchData{
 ID: 12345,
 Name: "Test User",
 Tags: []string{"go", "backend", "performance"},
 Score: 98.5,
 Active: true,
 }

 b.ResetTimer()
 for i := 0; i < b.N; i++ {
 _, _ = json.Marshal(data)
 }
}

func BenchmarkJSONUnmarshal(b *testing.B) {
 jsonData := []byte(`{"id":12345,"name":"Test User","tags":["go","backend","performance"],"score":98.5,"active":true}`)
 var data BenchData

 b.ResetTimer()
 for i := 0; i < b.N; i++ {
 _ = json.Unmarshal(jsonData, &data)
 }
}

func BenchmarkGoroutineCreation(b *testing.B) {
 done := make(chan struct{})
 b.ResetTimer()
 for i := 0; i < b.N; i++ {
 go func() {
 done <- struct{}{}
 }()
 <-done
 }
}

func BenchmarkChannelSend(b *testing.B) {
 ch := make(chan int, 1)
 b.ResetTimer()
 for i := 0; i < b.N; i++ {
 ch <- i
 <-ch
 }
}

// 実行: go test -bench=. -benchmem

実行結果例

<!-- Go 1.23 ベンチマーク結果 (go test -bench=. -benchmem) -->
BenchmarkJSONMarshal-8 5000000 280 ns/op 144 B/op 2 allocs/op
BenchmarkJSONUnmarshal-8 2000000 650 ns/op 288 B/op 8 allocs/op
BenchmarkGoroutineCreation-8 10000000 120 ns/op 0 B/op 0 allocs/op
BenchmarkChannelSend-8 50000000 32 ns/op 0 B/op 0 allocs/op

2025年の採用動向

業界別トレンド

adoption_trends_2025:
 cloud_providers:
 trend: "急増"
 percentage: 78%
 note: "AWS, GCP, Azureの内部ツールの大半がGo製"

 fintech:
 trend: "高成長"
 percentage: 65%
 note: "低レイテンシー要求による採用"

 gaming:
 trend: "成長"
 percentage: 45%
 note: "マッチメイキング、リアルタイムサーバー"

 ecommerce:
 trend: "安定成長"
 percentage: 55%
 note: "高トラフィック対応"

 media_streaming:
 trend: "高成長"
 percentage: 60%
 note: "エッジ配信、トランスコーディング"

開発者調査結果

項目2023年2024年2025年予測
プロフェッショナル利用率13.2%14.8%16.5%
学習意欲(未経験者)18.5%21.2%24.0%
Stack Overflow人気8位7位6位
GitHub新規プロジェクト12%14%16%

今後の展望

Go 1.24以降の予定

go_roadmap:
 go_1_24_2025:
 release: "2025年2月予定"
 features:
 - ジェネリック型の改善
 - go/typesパッケージの拡張
 - ビルドキャッシュの最適化
 - WASI Preview 2サポート

 go_1_25_2025:
 release: "2025年8月予定"
 potential_features:
 - 構造体のフィールドデフォルト値
 - エラーハンドリングの改善
 - さらなるイテレーター機能拡張

 long_term:
 - sum types(直和型)の検討
 - Enum型の導入検討
 - コルーチンの改善
 - WebAssembly Component Model対応

市場予測

market_forecast:
 backend_language_share_2027:
 go: 18%
 java: 25%
 python: 20%
 javascript_node: 15%
 rust: 8%
 others: 14%

 key_drivers:
 - クラウドネイティブ需要の拡大
 - マイクロサービスアーキテクチャの普及
 - DevOps/SREツールチェーンの標準化
 - AI/ML推論サーバーでの採用
 - エッジコンピューティングの成長

学習リソース

公式リソース

# Goのインストール
# macOS
brew install go

# Linux
wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz

# 公式チュートリアル
go doc -http=:6060

# The Go Tour
go install golang.org/x/website/tour@latest && tour

推奨学習パス

learning_path:
 beginner:
 - "A Tour of Go(公式チュートリアル)"
 - "Go by Example"
 - "Effective Go"

 intermediate:
 - "Concurrency in Go(O'Reilly)"
 - "Go言語による並行処理"
 - "標準ライブラリのソースコード読解"

 advanced:
 - "Go Internals"
 - "High Performance Go"
 - "OSSプロジェクトへの貢献"

まとめ

Go言語は2025年、バックエンド開発において確固たる主流言語の地位を確立しました。

Goの強み

  • シンプルさ: 学習が容易で、コードの可読性が高い
  • 並行処理: goroutineとchannelによる直感的な並行プログラミング
  • パフォーマンス: ネイティブコンパイルによる高速実行
  • クラウドネイティブ: Kubernetes、Docker等のエコシステムとの親和性
  • 高速コンパイル: 大規模プロジェクトでも数秒でビルド完了
  • シングルバイナリ: デプロイが容易な単一実行ファイル

採用を検討すべき場面

  1. マイクロサービスアーキテクチャの構築
  2. 高並行処理が必要なシステム
  3. クラウドネイティブアプリケーション開発
  4. DevOpsツールの開発
  5. API サーバーWebバックエンド

Go言語は、今後もクラウドネイティブ時代のバックエンド開発において中心的な役割を果たし続けるでしょう。

参考リンク

参考リソース

← 一覧に戻る
PR
PR
PR
PR