THRIFT-5744: Switch to slog for go library

Client: go
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index c0b5a97..aeb1614 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -82,8 +82,8 @@
     strategy:
       matrix:
         go:
-          - '1.20'
           - '1.21'
+          - '1.22'
       fail-fast: false
     steps:
       - uses: actions/checkout@v4
@@ -127,7 +127,7 @@
         run: make -C test/go precross
 
       - name: Upload go precross artifacts
-        if: matrix.go == '1.21'
+        if: matrix.go == '1.22'
         uses: actions/upload-artifact@v3
         with:
           name: go-precross
diff --git a/LANGUAGES.md b/LANGUAGES.md
index 236007f..4952ade 100644
--- a/LANGUAGES.md
+++ b/LANGUAGES.md
@@ -163,7 +163,7 @@
 <td align=left><a href="https://github.com/apache/thrift/blob/master/lib/go/README.md">Go</a></td>
 <!-- Since -----------------><td>0.7.0</td>
 <!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>1.20</td><td>1.21</td>
+<!-- Language Levels -------><td>1.21</td><td>1.22</td>
 <!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
 <!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
 <!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
diff --git a/go.mod b/go.mod
index 7be4256..b435d78 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
 module github.com/apache/thrift
 
-go 1.20
+go 1.21
diff --git a/lib/go/test/fuzz/go.mod b/lib/go/test/fuzz/go.mod
index 4ff6c5d..b7ddd5f 100644
--- a/lib/go/test/fuzz/go.mod
+++ b/lib/go/test/fuzz/go.mod
@@ -1,6 +1,6 @@
 module github.com/apache/thrift/lib/go/test/fuzz
 
-go 1.20
+go 1.21
 
 require github.com/apache/thrift v0.0.0-00010101000000-000000000000
 
diff --git a/lib/go/test/go.mod b/lib/go/test/go.mod
index 59535e6..0c032b7 100644
--- a/lib/go/test/go.mod
+++ b/lib/go/test/go.mod
@@ -1,6 +1,6 @@
 module github.com/apache/thrift/lib/go/test
 
-go 1.20
+go 1.21
 
 require (
 	github.com/apache/thrift v0.0.0-00010101000000-000000000000
diff --git a/lib/go/thrift/debug_protocol.go b/lib/go/thrift/debug_protocol.go
index 83ccad9..d730411 100644
--- a/lib/go/thrift/debug_protocol.go
+++ b/lib/go/thrift/debug_protocol.go
@@ -21,7 +21,7 @@
 
 import (
 	"context"
-	"fmt"
+	"log/slog"
 )
 
 type TDebugProtocol struct {
@@ -34,7 +34,11 @@
 	// If Logger is nil, StdLogger using stdlib log package with os.Stderr
 	// will be used. If disable logging is desired, set Logger to NopLogger
 	// explicitly instead of leaving it as nil/unset.
-	Logger    Logger
+	//
+	// Deprecated: TDebugProtocol always use slog at debug level now.
+	// This field will be removed in a future version.
+	Logger Logger
+
 	LogPrefix string
 
 	// Optional. An TProtocol to duplicate everything read/written from Delegate.
@@ -86,13 +90,16 @@
 	}
 }
 
-func (tdp *TDebugProtocol) logf(format string, v ...interface{}) {
-	fallbackLogger(tdp.Logger)(fmt.Sprintf(format, v...))
-}
-
 func (tdp *TDebugProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error {
 	err := tdp.Delegate.WriteMessageBegin(ctx, name, typeId, seqid)
-	tdp.logf("%sWriteMessageBegin(name=%#v, typeId=%#v, seqid=%#v) => %#v", tdp.LogPrefix, name, typeId, seqid, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteMessageBegin",
+		"name", name,
+		"typeId", typeId,
+		"seqid", seqid,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid)
 	}
@@ -100,7 +107,11 @@
 }
 func (tdp *TDebugProtocol) WriteMessageEnd(ctx context.Context) error {
 	err := tdp.Delegate.WriteMessageEnd(ctx)
-	tdp.logf("%sWriteMessageEnd() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteMessageEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMessageEnd(ctx)
 	}
@@ -108,7 +119,12 @@
 }
 func (tdp *TDebugProtocol) WriteStructBegin(ctx context.Context, name string) error {
 	err := tdp.Delegate.WriteStructBegin(ctx, name)
-	tdp.logf("%sWriteStructBegin(name=%#v) => %#v", tdp.LogPrefix, name, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteStructBegin",
+		"name", name,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteStructBegin(ctx, name)
 	}
@@ -116,7 +132,11 @@
 }
 func (tdp *TDebugProtocol) WriteStructEnd(ctx context.Context) error {
 	err := tdp.Delegate.WriteStructEnd(ctx)
-	tdp.logf("%sWriteStructEnd() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteStructEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteStructEnd(ctx)
 	}
@@ -124,7 +144,14 @@
 }
 func (tdp *TDebugProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error {
 	err := tdp.Delegate.WriteFieldBegin(ctx, name, typeId, id)
-	tdp.logf("%sWriteFieldBegin(name=%#v, typeId=%#v, id%#v) => %#v", tdp.LogPrefix, name, typeId, id, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteFieldBegin",
+		"name", name,
+		"typeId", typeId,
+		"id", id,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id)
 	}
@@ -132,7 +159,11 @@
 }
 func (tdp *TDebugProtocol) WriteFieldEnd(ctx context.Context) error {
 	err := tdp.Delegate.WriteFieldEnd(ctx)
-	tdp.logf("%sWriteFieldEnd() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteFieldEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteFieldEnd(ctx)
 	}
@@ -140,7 +171,11 @@
 }
 func (tdp *TDebugProtocol) WriteFieldStop(ctx context.Context) error {
 	err := tdp.Delegate.WriteFieldStop(ctx)
-	tdp.logf("%sWriteFieldStop() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteFieldStop",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteFieldStop(ctx)
 	}
@@ -148,7 +183,14 @@
 }
 func (tdp *TDebugProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
 	err := tdp.Delegate.WriteMapBegin(ctx, keyType, valueType, size)
-	tdp.logf("%sWriteMapBegin(keyType=%#v, valueType=%#v, size=%#v) => %#v", tdp.LogPrefix, keyType, valueType, size, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteMapBegin",
+		"keyType", keyType,
+		"valueType", valueType,
+		"size", size,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size)
 	}
@@ -156,7 +198,11 @@
 }
 func (tdp *TDebugProtocol) WriteMapEnd(ctx context.Context) error {
 	err := tdp.Delegate.WriteMapEnd(ctx)
-	tdp.logf("%sWriteMapEnd() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteMapEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMapEnd(ctx)
 	}
@@ -164,7 +210,13 @@
 }
 func (tdp *TDebugProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
 	err := tdp.Delegate.WriteListBegin(ctx, elemType, size)
-	tdp.logf("%sWriteListBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteListBegin",
+		"elemType", elemType,
+		"size", size,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteListBegin(ctx, elemType, size)
 	}
@@ -172,7 +224,11 @@
 }
 func (tdp *TDebugProtocol) WriteListEnd(ctx context.Context) error {
 	err := tdp.Delegate.WriteListEnd(ctx)
-	tdp.logf("%sWriteListEnd() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteListEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteListEnd(ctx)
 	}
@@ -180,7 +236,13 @@
 }
 func (tdp *TDebugProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
 	err := tdp.Delegate.WriteSetBegin(ctx, elemType, size)
-	tdp.logf("%sWriteSetBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteSetBegin",
+		"elemType", elemType,
+		"size", size,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteSetBegin(ctx, elemType, size)
 	}
@@ -188,7 +250,11 @@
 }
 func (tdp *TDebugProtocol) WriteSetEnd(ctx context.Context) error {
 	err := tdp.Delegate.WriteSetEnd(ctx)
-	tdp.logf("%sWriteSetEnd() => %#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteSetEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteSetEnd(ctx)
 	}
@@ -196,7 +262,12 @@
 }
 func (tdp *TDebugProtocol) WriteBool(ctx context.Context, value bool) error {
 	err := tdp.Delegate.WriteBool(ctx, value)
-	tdp.logf("%sWriteBool(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteBool",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteBool(ctx, value)
 	}
@@ -204,7 +275,12 @@
 }
 func (tdp *TDebugProtocol) WriteByte(ctx context.Context, value int8) error {
 	err := tdp.Delegate.WriteByte(ctx, value)
-	tdp.logf("%sWriteByte(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteByte",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteByte(ctx, value)
 	}
@@ -212,7 +288,12 @@
 }
 func (tdp *TDebugProtocol) WriteI16(ctx context.Context, value int16) error {
 	err := tdp.Delegate.WriteI16(ctx, value)
-	tdp.logf("%sWriteI16(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteI16",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteI16(ctx, value)
 	}
@@ -220,7 +301,12 @@
 }
 func (tdp *TDebugProtocol) WriteI32(ctx context.Context, value int32) error {
 	err := tdp.Delegate.WriteI32(ctx, value)
-	tdp.logf("%sWriteI32(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteI32",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteI32(ctx, value)
 	}
@@ -228,7 +314,12 @@
 }
 func (tdp *TDebugProtocol) WriteI64(ctx context.Context, value int64) error {
 	err := tdp.Delegate.WriteI64(ctx, value)
-	tdp.logf("%sWriteI64(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteI64",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteI64(ctx, value)
 	}
@@ -236,7 +327,12 @@
 }
 func (tdp *TDebugProtocol) WriteDouble(ctx context.Context, value float64) error {
 	err := tdp.Delegate.WriteDouble(ctx, value)
-	tdp.logf("%sWriteDouble(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteDouble",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteDouble(ctx, value)
 	}
@@ -244,7 +340,12 @@
 }
 func (tdp *TDebugProtocol) WriteString(ctx context.Context, value string) error {
 	err := tdp.Delegate.WriteString(ctx, value)
-	tdp.logf("%sWriteString(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteString",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteString(ctx, value)
 	}
@@ -252,7 +353,12 @@
 }
 func (tdp *TDebugProtocol) WriteBinary(ctx context.Context, value []byte) error {
 	err := tdp.Delegate.WriteBinary(ctx, value)
-	tdp.logf("%sWriteBinary(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteBinary",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteBinary(ctx, value)
 	}
@@ -260,7 +366,12 @@
 }
 func (tdp *TDebugProtocol) WriteUUID(ctx context.Context, value Tuuid) error {
 	err := tdp.Delegate.WriteUUID(ctx, value)
-	tdp.logf("%sWriteUUID(value=%#v) => %#v", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"WriteUUID",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteUUID(ctx, value)
 	}
@@ -269,7 +380,14 @@
 
 func (tdp *TDebugProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) {
 	name, typeId, seqid, err = tdp.Delegate.ReadMessageBegin(ctx)
-	tdp.logf("%sReadMessageBegin() (name=%#v, typeId=%#v, seqid=%#v, err=%#v)", tdp.LogPrefix, name, typeId, seqid, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadMessageBegin",
+		"name", name,
+		"typeId", typeId,
+		"seqid", seqid,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid)
 	}
@@ -277,7 +395,11 @@
 }
 func (tdp *TDebugProtocol) ReadMessageEnd(ctx context.Context) (err error) {
 	err = tdp.Delegate.ReadMessageEnd(ctx)
-	tdp.logf("%sReadMessageEnd() err=%#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadMessageEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMessageEnd(ctx)
 	}
@@ -285,7 +407,12 @@
 }
 func (tdp *TDebugProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
 	name, err = tdp.Delegate.ReadStructBegin(ctx)
-	tdp.logf("%sReadStructBegin() (name%#v, err=%#v)", tdp.LogPrefix, name, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadStructBegin",
+		"name", name,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteStructBegin(ctx, name)
 	}
@@ -293,7 +420,11 @@
 }
 func (tdp *TDebugProtocol) ReadStructEnd(ctx context.Context) (err error) {
 	err = tdp.Delegate.ReadStructEnd(ctx)
-	tdp.logf("%sReadStructEnd() err=%#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadStructEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteStructEnd(ctx)
 	}
@@ -301,7 +432,14 @@
 }
 func (tdp *TDebugProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) {
 	name, typeId, id, err = tdp.Delegate.ReadFieldBegin(ctx)
-	tdp.logf("%sReadFieldBegin() (name=%#v, typeId=%#v, id=%#v, err=%#v)", tdp.LogPrefix, name, typeId, id, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadFieldBegin",
+		"name", name,
+		"typeId", typeId,
+		"id", id,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id)
 	}
@@ -309,7 +447,11 @@
 }
 func (tdp *TDebugProtocol) ReadFieldEnd(ctx context.Context) (err error) {
 	err = tdp.Delegate.ReadFieldEnd(ctx)
-	tdp.logf("%sReadFieldEnd() err=%#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadFieldEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteFieldEnd(ctx)
 	}
@@ -317,7 +459,14 @@
 }
 func (tdp *TDebugProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) {
 	keyType, valueType, size, err = tdp.Delegate.ReadMapBegin(ctx)
-	tdp.logf("%sReadMapBegin() (keyType=%#v, valueType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, keyType, valueType, size, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadMapBegin",
+		"keyType", keyType,
+		"valueType", valueType,
+		"size", size,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size)
 	}
@@ -325,7 +474,11 @@
 }
 func (tdp *TDebugProtocol) ReadMapEnd(ctx context.Context) (err error) {
 	err = tdp.Delegate.ReadMapEnd(ctx)
-	tdp.logf("%sReadMapEnd() err=%#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadMapEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteMapEnd(ctx)
 	}
@@ -333,7 +486,13 @@
 }
 func (tdp *TDebugProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) {
 	elemType, size, err = tdp.Delegate.ReadListBegin(ctx)
-	tdp.logf("%sReadListBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadListBegin",
+		"elemType", elemType,
+		"size", size,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteListBegin(ctx, elemType, size)
 	}
@@ -341,7 +500,11 @@
 }
 func (tdp *TDebugProtocol) ReadListEnd(ctx context.Context) (err error) {
 	err = tdp.Delegate.ReadListEnd(ctx)
-	tdp.logf("%sReadListEnd() err=%#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadListEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteListEnd(ctx)
 	}
@@ -349,7 +512,13 @@
 }
 func (tdp *TDebugProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) {
 	elemType, size, err = tdp.Delegate.ReadSetBegin(ctx)
-	tdp.logf("%sReadSetBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadSetBegin",
+		"elemType", elemType,
+		"size", size,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteSetBegin(ctx, elemType, size)
 	}
@@ -357,7 +526,11 @@
 }
 func (tdp *TDebugProtocol) ReadSetEnd(ctx context.Context) (err error) {
 	err = tdp.Delegate.ReadSetEnd(ctx)
-	tdp.logf("%sReadSetEnd() err=%#v", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadSetEnd",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteSetEnd(ctx)
 	}
@@ -365,7 +538,12 @@
 }
 func (tdp *TDebugProtocol) ReadBool(ctx context.Context) (value bool, err error) {
 	value, err = tdp.Delegate.ReadBool(ctx)
-	tdp.logf("%sReadBool() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadBool",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteBool(ctx, value)
 	}
@@ -373,7 +551,12 @@
 }
 func (tdp *TDebugProtocol) ReadByte(ctx context.Context) (value int8, err error) {
 	value, err = tdp.Delegate.ReadByte(ctx)
-	tdp.logf("%sReadByte() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadByte",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteByte(ctx, value)
 	}
@@ -381,7 +564,12 @@
 }
 func (tdp *TDebugProtocol) ReadI16(ctx context.Context) (value int16, err error) {
 	value, err = tdp.Delegate.ReadI16(ctx)
-	tdp.logf("%sReadI16() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadI16",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteI16(ctx, value)
 	}
@@ -389,7 +577,12 @@
 }
 func (tdp *TDebugProtocol) ReadI32(ctx context.Context) (value int32, err error) {
 	value, err = tdp.Delegate.ReadI32(ctx)
-	tdp.logf("%sReadI32() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadI32",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteI32(ctx, value)
 	}
@@ -397,7 +590,12 @@
 }
 func (tdp *TDebugProtocol) ReadI64(ctx context.Context) (value int64, err error) {
 	value, err = tdp.Delegate.ReadI64(ctx)
-	tdp.logf("%sReadI64() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadI64",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteI64(ctx, value)
 	}
@@ -405,7 +603,12 @@
 }
 func (tdp *TDebugProtocol) ReadDouble(ctx context.Context) (value float64, err error) {
 	value, err = tdp.Delegate.ReadDouble(ctx)
-	tdp.logf("%sReadDouble() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadDouble",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteDouble(ctx, value)
 	}
@@ -413,7 +616,12 @@
 }
 func (tdp *TDebugProtocol) ReadString(ctx context.Context) (value string, err error) {
 	value, err = tdp.Delegate.ReadString(ctx)
-	tdp.logf("%sReadString() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadString",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteString(ctx, value)
 	}
@@ -421,7 +629,12 @@
 }
 func (tdp *TDebugProtocol) ReadBinary(ctx context.Context) (value []byte, err error) {
 	value, err = tdp.Delegate.ReadBinary(ctx)
-	tdp.logf("%sReadBinary() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadBinary",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteBinary(ctx, value)
 	}
@@ -429,7 +642,12 @@
 }
 func (tdp *TDebugProtocol) ReadUUID(ctx context.Context) (value Tuuid, err error) {
 	value, err = tdp.Delegate.ReadUUID(ctx)
-	tdp.logf("%sReadUUID() (value=%#v, err=%#v)", tdp.LogPrefix, value, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"ReadUUID",
+		"value", value,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.WriteUUID(ctx, value)
 	}
@@ -437,7 +655,12 @@
 }
 func (tdp *TDebugProtocol) Skip(ctx context.Context, fieldType TType) (err error) {
 	err = tdp.Delegate.Skip(ctx, fieldType)
-	tdp.logf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"Skip",
+		"fieldType", fieldType,
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.Skip(ctx, fieldType)
 	}
@@ -445,7 +668,11 @@
 }
 func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) {
 	err = tdp.Delegate.Flush(ctx)
-	tdp.logf("%sFlush() (err=%#v)", tdp.LogPrefix, err)
+	slog.DebugContext(
+		ctx,
+		tdp.LogPrefix+"Flush",
+		"err", err,
+	)
 	if tdp.DuplicateTo != nil {
 		tdp.DuplicateTo.Flush(ctx)
 	}
diff --git a/lib/go/thrift/logger.go b/lib/go/thrift/logger.go
index c42aac9..4a0affe 100644
--- a/lib/go/thrift/logger.go
+++ b/lib/go/thrift/logger.go
@@ -35,14 +35,23 @@
 //
 // See https://issues.apache.org/jira/browse/THRIFT-4985 for the design
 // discussion behind it.
+//
+// Deprecated: This is no longer used by any thrift go library code,
+// will be removed in the future version.
 type Logger func(msg string)
 
 // NopLogger is a Logger implementation that does nothing.
+//
+// Deprecated: This is no longer used by any thrift go library code,
+// will be removed in the future version.
 func NopLogger(msg string) {}
 
 // StdLogger wraps stdlib log package into a Logger.
 //
 // If logger passed in is nil, it will fallback to use stderr and default flags.
+//
+// Deprecated: This is no longer used by any thrift go library code,
+// will be removed in the future version.
 func StdLogger(logger *log.Logger) Logger {
 	if logger == nil {
 		logger = log.New(os.Stderr, "", log.LstdFlags)
@@ -55,6 +64,9 @@
 // TestLogger is a Logger implementation can be used in test codes.
 //
 // It fails the test when being called.
+//
+// Deprecated: This is no longer used by any thrift go library code,
+// will be removed in the future version.
 func TestLogger(tb testing.TB) Logger {
 	return func(msg string) {
 		tb.Errorf("logger called with msg: %q", msg)
diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go
index d4f555c..a8634fc 100644
--- a/lib/go/thrift/simple_server.go
+++ b/lib/go/thrift/simple_server.go
@@ -22,8 +22,8 @@
 import (
 	"context"
 	"errors"
-	"fmt"
 	"io"
+	"log/slog"
 	"net"
 	"sync"
 	"sync/atomic"
@@ -70,7 +70,7 @@
 	// Headers to auto forward in THeaderProtocol
 	forwardHeaders []string
 
-	logger Logger
+	logContext atomic.Pointer[context.Context]
 }
 
 func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer {
@@ -179,8 +179,18 @@
 //
 // If no logger was set before Serve is called, a default logger using standard
 // log library will be used.
-func (p *TSimpleServer) SetLogger(logger Logger) {
-	p.logger = logger
+//
+// Deprecated: The logging inside TSimpleServer is now done via slog on error
+// level, this does nothing now. It will be removed in a future version.
+func (p *TSimpleServer) SetLogger(_ Logger) {}
+
+// SetLogContext sets the context to be used when logging errors inside
+// TSimpleServer.
+//
+// If this is not called before calling Serve, context.Background() will be
+// used.
+func (p *TSimpleServer) SetLogContext(ctx context.Context) {
+	p.logContext.Store(&ctx)
 }
 
 func (p *TSimpleServer) innerAccept() (int32, error) {
@@ -202,7 +212,8 @@
 			defer p.wg.Done()
 			defer cancel()
 			if err := p.processRequests(client); err != nil {
-				p.logger(fmt.Sprintf("error processing request: %v", err))
+				ctx := p.logContext.Load()
+				slog.ErrorContext(*ctx, "error processing request", "err", err)
 			}
 		}()
 
@@ -233,7 +244,7 @@
 }
 
 func (p *TSimpleServer) Serve() error {
-	p.logger = fallbackLogger(p.logger)
+	p.logContext.CompareAndSwap(nil, Pointer(context.Background()))
 
 	err := p.Listen()
 	if err != nil {
diff --git a/test/go/go.mod b/test/go/go.mod
index 723069b..f69cdb4 100644
--- a/test/go/go.mod
+++ b/test/go/go.mod
@@ -1,6 +1,6 @@
 module github.com/apache/thrift/test/go
 
-go 1.20
+go 1.21
 
 require (
 	github.com/apache/thrift v0.0.0-00010101000000-000000000000
@@ -9,7 +9,7 @@
 
 require (
 	golang.org/x/mod v0.4.2 // indirect
-	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
 	golang.org/x/tools v0.1.1 // indirect
 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 )
diff --git a/test/go/go.sum b/test/go/go.sum
index b6ad545..6904b3e 100644
--- a/test/go/go.sum
+++ b/test/go/go.sum
@@ -16,8 +16,6 @@
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
-golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=