Skip to content

Commit e727a3b

Browse files
committed
box: box.New returns an error instead of panic
Method `box.New` now returns (*Box, error), because avoiding panics entirely in third-party libraries is ideal, since we can't break compatibility. Nonetheless, there is still a way to panic on error, via implemented `box.MustNew` wrapper. Part of #448
1 parent 6111b79 commit e727a3b

File tree

6 files changed

+119
-39
lines changed

6 files changed

+119
-39
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1111
### Added
1212

1313
* New types for MessagePack extensions compatible with go-option (#459).
14+
* Added `box.MustNew` wrapper for `box.New`: panics when `box.New` returns an error (#448).
1415

1516
### Changed
1617

1718
* Required Go version is `1.24` now (#456).
1819

1920
### Fixed
2021

22+
* `box.New` returns an error instead of panic (#448).
23+
2124
## [v2.4.1] - 2025-10-16
2225

2326
This maintenance release marks the end of active development on the `v2`

box/box.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package box
22

33
import (
4+
"errors"
5+
46
"github.com/tarantool/go-tarantool/v3"
57
)
68

@@ -11,16 +13,25 @@ type Box struct {
1113
}
1214

1315
// New returns a new instance of the box structure, which implements the Box interface.
14-
func New(conn tarantool.Doer) *Box {
16+
func New(conn tarantool.Doer) (*Box, error) {
1517
if conn == nil {
16-
// Check if the provided Tarantool connection is nil, and if it is, panic with an error
17-
// message. panic early helps to catch and fix nil pointer issues in the code.
18-
panic("tarantool connection cannot be nil")
18+
return nil, errors.New("tarantool connection cannot be nil")
1919
}
2020

2121
return &Box{
2222
conn: conn, // Assigns the provided Tarantool connection.
23+
}, nil
24+
}
25+
26+
// MustNew returns a new instance of the box structure, which implements the Box interface.
27+
func MustNew(conn tarantool.Doer) *Box {
28+
b, err := New(conn)
29+
if err != nil {
30+
// Check if the provided Tarantool connection is nil, and if it is, panic with an error
31+
// message. panic early helps to catch and fix nil pointer issues in the code
32+
panic(err)
2333
}
34+
return b
2435
}
2536

2637
// Schema returns a new Schema instance, providing access to schema-related operations.

box/box_test.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,15 @@ import (
1515
func TestNew(t *testing.T) {
1616
t.Parallel()
1717

18+
_, err := box.New(nil)
19+
require.Error(t, err)
20+
}
21+
22+
func TestMustNew(t *testing.T) {
23+
t.Parallel()
24+
1825
// Create a box instance with a nil connection. This should lead to a panic.
19-
require.Panics(t, func() { box.New(nil) })
26+
require.Panics(t, func() { box.MustNew(nil) })
2027
}
2128

2229
func TestMocked_BoxInfo(t *testing.T) {
@@ -37,7 +44,8 @@ func TestMocked_BoxInfo(t *testing.T) {
3744
mock := test_helpers.NewMockDoer(t,
3845
test_helpers.NewMockResponse(t, data),
3946
)
40-
b := box.New(&mock)
47+
b, err := box.New(&mock)
48+
require.NoError(t, err)
4149

4250
info, err := b.Info()
4351
require.NoError(t, err)
@@ -57,7 +65,8 @@ func TestMocked_BoxSchemaUserInfo(t *testing.T) {
5765
mock := test_helpers.NewMockDoer(t,
5866
test_helpers.NewMockResponse(t, data),
5967
)
60-
b := box.New(&mock)
68+
b, err := box.New(&mock)
69+
require.NoError(t, err)
6170

6271
privs, err := b.Schema().User().Info(context.Background(), "username")
6372
require.NoError(t, err)
@@ -82,8 +91,9 @@ func TestMocked_BoxSessionSu(t *testing.T) {
8291
test_helpers.NewMockResponse(t, []interface{}{}),
8392
errors.New("user not found or supplied credentials are invalid"),
8493
)
85-
b := box.New(&mock)
94+
b, err := box.New(&mock)
95+
require.NoError(t, err)
8696

87-
err := b.Session().Su(context.Background(), "admin")
97+
err = b.Session().Su(context.Background(), "admin")
8898
require.NoError(t, err)
8999
}

box/example_test.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ func ExampleBox_Info() {
4545

4646
// Or use simple Box implementation.
4747

48-
b := box.New(client)
48+
b, err := box.New(client)
49+
if err != nil {
50+
log.Fatalf("Failed get box info: %s", err)
51+
}
4952

5053
info, err := b.Info()
5154
if err != nil {
@@ -88,7 +91,11 @@ func ExampleSchemaUser_Exists() {
8891
}
8992

9093
// Or use simple User implementation.
91-
b := box.New(client)
94+
b, err := box.New(client)
95+
if err != nil {
96+
log.Fatalf("Failed get box info: %s", err)
97+
}
98+
9299
exists, err := b.Schema().User().Exists(ctx, "user")
93100
if err != nil {
94101
log.Fatalf("Failed get box schema user exists with error: %s", err)
@@ -120,7 +127,11 @@ func ExampleSchemaUser_Create() {
120127
}
121128

122129
// Create SchemaUser.
123-
schemaUser := box.New(client).Schema().User()
130+
b, err := box.New(client)
131+
if err != nil {
132+
log.Fatalf("Failed to connect: %s", err)
133+
}
134+
schemaUser := b.Schema().User()
124135

125136
// Create a new user.
126137
username := "new_user"
@@ -153,7 +164,11 @@ func ExampleSchemaUser_Drop() {
153164
}
154165

155166
// Create SchemaUser.
156-
schemaUser := box.New(client).Schema().User()
167+
b, err := box.New(client)
168+
if err != nil {
169+
log.Fatalf("Failed to connect: %s", err)
170+
}
171+
schemaUser := b.Schema().User()
157172

158173
// Drop an existing user.
159174
username := "new_user"
@@ -192,7 +207,11 @@ func ExampleSchemaUser_Password() {
192207
}
193208

194209
// Create SchemaUser.
195-
schemaUser := box.New(client).Schema().User()
210+
b, err := box.New(client)
211+
if err != nil {
212+
log.Fatalf("Failed to connect: %s", err)
213+
}
214+
schemaUser := b.Schema().User()
196215

197216
// Get the password hash.
198217
password := "my-password"
@@ -221,7 +240,11 @@ func ExampleSchemaUser_Info() {
221240
}
222241

223242
// Create SchemaUser.
224-
schemaUser := box.New(client).Schema().User()
243+
b, err := box.New(client)
244+
if err != nil {
245+
log.Fatalf("Failed to connect: %s", err)
246+
}
247+
schemaUser := b.Schema().User()
225248

226249
info, err := schemaUser.Info(ctx, "test")
227250
if err != nil {

box/session_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import (
1010
)
1111

1212
func TestBox_Session(t *testing.T) {
13-
b := box.New(th.Ptr(th.NewMockDoer(t)))
13+
b, err := box.New(th.Ptr(th.NewMockDoer(t)))
14+
require.NoError(t, err)
1415
require.NotNil(t, b.Session())
1516
}
1617

0 commit comments

Comments
 (0)