or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dotnet.mdexpression-factory.mdgo.mdindex.mdjava.mdjavascript-typescript.mdparameter-types.mdpython.mdruby.md

go.mddocs/

0

# Go Implementation

1

2

Go implementation with idiomatic Go patterns, reflection-based type handling, comprehensive error management, and full integration with Go testing frameworks.

3

4

## Package Information

5

6

- **Module**: `github.com/cucumber/cucumber-expressions/go/v18`

7

- **Package**: `cucumberexpressions`

8

- **Language**: Go 1.18+

9

- **Installation**: `go get github.com/cucumber/cucumber-expressions/go/v18`

10

11

## Core Imports

12

13

```go

14

import (

15

"github.com/cucumber/cucumber-expressions/go/v18"

16

"reflect"

17

"regexp"

18

)

19

```

20

21

## Capabilities

22

23

### Expression Creation and Matching

24

25

Create and match Cucumber expressions with Go-style error handling and type reflection.

26

27

```go { .api }

28

// CucumberExpression represents a parsed Cucumber expression

29

type CucumberExpression struct {

30

source string

31

parameterTypes []*ParameterType

32

treeRegexp *TreeRegexp

33

parameterTypeRegistry *ParameterTypeRegistry

34

}

35

36

// NewCucumberExpression creates a new Cucumber expression

37

// Returns Expression interface and error for Go error handling patterns

38

func NewCucumberExpression(expression string, parameterTypeRegistry *ParameterTypeRegistry) (Expression, error)

39

40

// Match text against this expression and extract arguments

41

// Uses reflection for type hints to support Go's static typing

42

func (c *CucumberExpression) Match(text string, typeHints ...reflect.Type) ([]*Argument, error)

43

44

// Regexp returns the compiled regular expression

45

func (c *CucumberExpression) Regexp() *regexp.Regexp

46

47

// Source returns the original expression string

48

func (c *CucumberExpression) Source() string

49

50

// Expression interface that all expression types implement

51

type Expression interface {

52

// Match text and return arguments with optional type hints

53

Match(text string, typeHints ...reflect.Type) ([]*Argument, error)

54

55

// Get compiled regular expression

56

Regexp() *regexp.Regexp

57

58

// Get source expression string

59

Source() string

60

}

61

```

62

63

**Usage Examples:**

64

65

```go

66

package main

67

68

import (

69

"fmt"

70

"log"

71

"reflect"

72

73

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

74

)

75

76

func main() {

77

// Create registry with built-in parameter types

78

registry := cucumberexpressions.NewParameterTypeRegistry()

79

80

// Simple integer parameter

81

expr1, err := cucumberexpressions.NewCucumberExpression("I have {int} cucumbers", registry)

82

if err != nil {

83

log.Fatal(err)

84

}

85

86

args1, err := expr1.Match("I have 42 cucumbers")

87

if err != nil {

88

log.Fatal(err)

89

}

90

if args1 != nil {

91

fmt.Printf("Count: %v (type: %T)\n", args1[0].GetValue(), args1[0].GetValue()) // 42 (int)

92

}

93

94

// Multiple parameters

95

expr2, err := cucumberexpressions.NewCucumberExpression("User {word} has {int} items", registry)

96

if err != nil {

97

log.Fatal(err)

98

}

99

100

args2, err := expr2.Match("User alice has 42 items")

101

if err != nil {

102

log.Fatal(err)

103

}

104

if args2 != nil {

105

username := args2[0].GetValue() // "alice" (string)

106

itemCount := args2[1].GetValue() // 42 (int)

107

fmt.Printf("User: %v, Items: %v\n", username, itemCount)

108

}

109

110

// Optional text

111

expr3, err := cucumberexpressions.NewCucumberExpression("I have {int} cucumber(s)", registry)

112

if err != nil {

113

log.Fatal(err)

114

}

115

116

args3a, _ := expr3.Match("I have 1 cucumber")

117

args3b, _ := expr3.Match("I have 5 cucumbers")

118

fmt.Printf("Singular match: %v\n", args3a != nil) // true

119

fmt.Printf("Plural match: %v\n", args3b != nil) // true

120

121

// Alternative text

122

expr4, err := cucumberexpressions.NewCucumberExpression("I put it in my belly/stomach", registry)

123

if err != nil {

124

log.Fatal(err)

125

}

126

127

args4a, _ := expr4.Match("I put it in my belly")

128

args4b, _ := expr4.Match("I put it in my stomach")

129

fmt.Printf("Belly match: %v\n", args4a != nil) // true

130

fmt.Printf("Stomach match: %v\n", args4b != nil) // true

131

132

// String parameters (removes quotes)

133

expr5, err := cucumberexpressions.NewCucumberExpression("I say {string}", registry)

134

if err != nil {

135

log.Fatal(err)

136

}

137

138

args5, err := expr5.Match(`I say "hello world"`)

139

if err != nil {

140

log.Fatal(err)

141

}

142

if args5 != nil {

143

fmt.Printf("Message: %v\n", args5[0].GetValue()) // "hello world" (without quotes)

144

}

145

146

// Type hints for anonymous parameters

147

expr6, err := cucumberexpressions.NewCucumberExpression("Value is {}", registry)

148

if err != nil {

149

log.Fatal(err)

150

}

151

152

args6, err := expr6.Match("Value is 42", reflect.TypeOf(0)) // Hint for int type

153

if err != nil {

154

log.Fatal(err)

155

}

156

if args6 != nil {

157

value := args6[0].GetValue()

158

fmt.Printf("Value: %v (type: %T)\n", value, value) // May be converted to int

159

}

160

}

161

```

162

163

### Parameter Type Definition

164

165

Define custom parameter types with Go-style struct initialization and function transformers.

166

167

```go { .api }

168

// ParameterType defines a parameter type with patterns and transformer

169

type ParameterType struct {

170

name string

171

regexps []*regexp.Regexp

172

type1 string

173

transform func(...*string) interface{}

174

useForSnippets bool

175

preferForRegexpMatch bool

176

useRegexpMatchAsStrongTypeHint bool

177

}

178

179

// NewParameterType creates a new parameter type with validation

180

func NewParameterType(

181

name string,

182

regexps []*regexp.Regexp,

183

type1 string,

184

transform func(...*string) interface{},

185

useForSnippets bool,

186

preferForRegexpMatch bool,

187

useRegexpMatchAsStrongTypeHint bool

188

) (*ParameterType, error)

189

190

// CheckParameterTypeName validates parameter type name

191

func CheckParameterTypeName(typeName string) error

192

193

// CompareParameterTypes compares two parameter types for sorting

194

func CompareParameterTypes(pt1, pt2 *ParameterType) int

195

196

// Accessor methods with Go naming conventions

197

func (p *ParameterType) Name() string

198

func (p *ParameterType) Regexps() []*regexp.Regexp

199

func (p *ParameterType) Type() string

200

func (p *ParameterType) UseForSnippets() bool

201

func (p *ParameterType) PreferForRegexpMatch() bool

202

func (p *ParameterType) UseRegexpMatchAsStrongTypeHint() bool

203

204

// Transform matched groups to target type

205

func (p *ParameterType) Transform(groupValues []*string) interface{}

206

```

207

208

**Usage Examples:**

209

210

```go

211

package main

212

213

import (

214

"fmt"

215

"log"

216

"regexp"

217

"strconv"

218

"strings"

219

"time"

220

221

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

222

)

223

224

// Custom types

225

type Color string

226

227

const (

228

Red Color = "RED"

229

Green Color = "GREEN"

230

Blue Color = "BLUE"

231

Yellow Color = "YELLOW"

232

)

233

234

type Point struct {

235

X, Y int

236

}

237

238

func (p Point) String() string {

239

return fmt.Sprintf("(%d, %d)", p.X, p.Y)

240

}

241

242

type Money struct {

243

Amount float64

244

Currency string

245

}

246

247

func (m Money) String() string {

248

return fmt.Sprintf("%.2f %s", m.Amount, m.Currency)

249

}

250

251

func main() {

252

registry := cucumberexpressions.NewParameterTypeRegistry()

253

254

// Color parameter type with enum-like behavior

255

colorRegexp, _ := regexp.Compile("red|green|blue|yellow")

256

colorType, err := cucumberexpressions.NewParameterType(

257

"color",

258

[]*regexp.Regexp{colorRegexp},

259

"Color",

260

func(args ...*string) interface{} {

261

if len(args) > 0 && args[0] != nil {

262

return Color(strings.ToUpper(*args[0]))

263

}

264

return nil

265

},

266

true, // useForSnippets

267

false, // preferForRegexpMatch

268

false, // useRegexpMatchAsStrongTypeHint

269

)

270

if err != nil {

271

log.Fatal(err)

272

}

273

274

// Point parameter type with multiple capture groups

275

pointRegexp, _ := regexp.Compile(`\((-?\d+),\s*(-?\d+)\)`)

276

pointType, err := cucumberexpressions.NewParameterType(

277

"point",

278

[]*regexp.Regexp{pointRegexp},

279

"Point",

280

func(args ...*string) interface{} {

281

if len(args) >= 2 && args[0] != nil && args[1] != nil {

282

x, _ := strconv.Atoi(*args[0])

283

y, _ := strconv.Atoi(*args[1])

284

return Point{X: x, Y: y}

285

}

286

return nil

287

},

288

true,

289

false,

290

false,

291

)

292

if err != nil {

293

log.Fatal(err)

294

}

295

296

// Date parameter type with time.Time

297

dateRegexp, _ := regexp.Compile(`(\d{4})-(\d{2})-(\d{2})`)

298

dateType, err := cucumberexpressions.NewParameterType(

299

"date",

300

[]*regexp.Regexp{dateRegexp},

301

"time.Time",

302

func(args ...*string) interface{} {

303

if len(args) >= 3 && args[0] != nil && args[1] != nil && args[2] != nil {

304

year, _ := strconv.Atoi(*args[0])

305

month, _ := strconv.Atoi(*args[1])

306

day, _ := strconv.Atoi(*args[2])

307

308

if month < 1 || month > 12 {

309

return fmt.Errorf("invalid month: %d", month)

310

}

311

if day < 1 || day > 31 {

312

return fmt.Errorf("invalid day: %d", day)

313

}

314

315

return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)

316

}

317

return nil

318

},

319

true,

320

false,

321

false,

322

)

323

if err != nil {

324

log.Fatal(err)

325

}

326

327

// Money parameter type with floating point

328

moneyRegexp, _ := regexp.Compile(`\$(\d+(?:\.\d{2})?) (USD|EUR|GBP)`)

329

moneyType, err := cucumberexpressions.NewParameterType(

330

"money",

331

[]*regexp.Regexp{moneyRegexp},

332

"Money",

333

func(args ...*string) interface{} {

334

if len(args) >= 2 && args[0] != nil && args[1] != nil {

335

amount, err := strconv.ParseFloat(*args[0], 64)

336

if err != nil {

337

return err

338

}

339

return Money{Amount: amount, Currency: strings.ToUpper(*args[1])}

340

}

341

return nil

342

},

343

true,

344

false,

345

false,

346

)

347

if err != nil {

348

log.Fatal(err)

349

}

350

351

// Register parameter types

352

err = registry.DefineParameterType(colorType)

353

if err != nil {

354

log.Fatal(err)

355

}

356

err = registry.DefineParameterType(pointType)

357

if err != nil {

358

log.Fatal(err)

359

}

360

err = registry.DefineParameterType(dateType)

361

if err != nil {

362

log.Fatal(err)

363

}

364

err = registry.DefineParameterType(moneyType)

365

if err != nil {

366

log.Fatal(err)

367

}

368

369

// Use in expressions

370

colorExpr, _ := cucumberexpressions.NewCucumberExpression("I have a {color} car", registry)

371

colorArgs, _ := colorExpr.Match("I have a red car")

372

if colorArgs != nil {

373

color := colorArgs[0].GetValue().(Color)

374

fmt.Printf("Color: %v\n", color) // RED

375

}

376

377

pointExpr, _ := cucumberexpressions.NewCucumberExpression("Move to {point}", registry)

378

pointArgs, _ := pointExpr.Match("Move to (10, -5)")

379

if pointArgs != nil {

380

point := pointArgs[0].GetValue().(Point)

381

fmt.Printf("Point: %v, X: %d, Y: %d\n", point, point.X, point.Y) // (10, -5), X: 10, Y: -5

382

}

383

384

dateExpr, _ := cucumberexpressions.NewCucumberExpression("Meeting on {date}", registry)

385

dateArgs, _ := dateExpr.Match("Meeting on 2023-12-25")

386

if dateArgs != nil {

387

date := dateArgs[0].GetValue().(time.Time)

388

fmt.Printf("Date: %v\n", date.Format("January 2, 2006")) // December 25, 2023

389

}

390

391

moneyExpr, _ := cucumberexpressions.NewCucumberExpression("Price is {money}", registry)

392

moneyArgs, _ := moneyExpr.Match("Price is $29.99 USD")

393

if moneyArgs != nil {

394

money := moneyArgs[0].GetValue().(Money)

395

fmt.Printf("Money: %v\n", money) // 29.99 USD

396

}

397

398

// Parameter type introspection

399

fmt.Printf("Color type name: %s\n", colorType.Name())

400

fmt.Printf("Color regexps: %v\n", colorType.Regexps())

401

fmt.Printf("Color use for snippets: %v\n", colorType.UseForSnippets())

402

}

403

```

404

405

### Parameter Type Registry

406

407

Go-style registry with map-based storage and error handling.

408

409

```go { .api }

410

// ParameterTypeRegistry manages parameter types with concurrent safety

411

type ParameterTypeRegistry struct {

412

parameterTypesByName map[string]*ParameterType

413

parameterTypesByRegexp map[string][]*ParameterType

414

defaultTransformer ParameterByTypeTransformer

415

}

416

417

// NewParameterTypeRegistry creates registry with built-in parameter types

418

func NewParameterTypeRegistry() *ParameterTypeRegistry

419

420

// LookupByTypeName finds parameter type by name

421

func (p *ParameterTypeRegistry) LookupByTypeName(name string) *ParameterType

422

423

// LookupByRegexp finds parameter type by regex pattern

424

func (p *ParameterTypeRegistry) LookupByRegexp(

425

parameterTypeRegexp string,

426

expressionRegexp *regexp.Regexp,

427

text string

428

) (*ParameterType, error)

429

430

// DefineParameterType registers a new parameter type

431

func (p *ParameterTypeRegistry) DefineParameterType(parameterType *ParameterType) error

432

433

// ParameterTypes returns all registered parameter types

434

func (p *ParameterTypeRegistry) ParameterTypes() []*ParameterType

435

436

// SetDefaultParameterTransformer sets transformer for anonymous parameters

437

func (p *ParameterTypeRegistry) SetDefaultParameterTransformer(transformer ParameterByTypeTransformer)

438

439

// ParameterByTypeTransformer interface for type-based parameter transformation

440

type ParameterByTypeTransformer interface {

441

Transform(fromValue string, toValueType reflect.Type) (interface{}, error)

442

}

443

```

444

445

**Usage Examples:**

446

447

```go

448

package main

449

450

import (

451

"fmt"

452

"log"

453

"reflect"

454

"regexp"

455

"strconv"

456

"strings"

457

458

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

459

)

460

461

// Custom transformer for anonymous parameters

462

type CustomTransformer struct{}

463

464

func (ct *CustomTransformer) Transform(fromValue string, toValueType reflect.Type) (interface{}, error) {

465

switch toValueType.Kind() {

466

case reflect.Int:

467

return strconv.Atoi(fromValue)

468

case reflect.Float64:

469

return strconv.ParseFloat(fromValue, 64)

470

case reflect.Bool:

471

return strconv.ParseBool(fromValue)

472

default:

473

return fromValue, nil

474

}

475

}

476

477

func main() {

478

registry := cucumberexpressions.NewParameterTypeRegistry()

479

480

// Check built-in types

481

intType := registry.LookupByTypeName("int")

482

if intType != nil {

483

fmt.Printf("Found int type: %s\n", intType.Name())

484

fmt.Printf("Int regexps: %v\n", intType.Regexps())

485

}

486

487

// List all parameter types

488

fmt.Println("All parameter types:")

489

for _, paramType := range registry.ParameterTypes() {

490

regexpStrs := make([]string, len(paramType.Regexps()))

491

for i, regex := range paramType.Regexps() {

492

regexpStrs[i] = regex.String()

493

}

494

fmt.Printf(" %s: %v\n", paramType.Name(), regexpStrs)

495

}

496

497

// Define custom parameter type

498

uuidRegexp, _ := regexp.Compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")

499

uuidType, err := cucumberexpressions.NewParameterType(

500

"uuid",

501

[]*regexp.Regexp{uuidRegexp},

502

"string",

503

func(args ...*string) interface{} {

504

if len(args) > 0 && args[0] != nil {

505

return strings.ToUpper(*args[0])

506

}

507

return nil

508

},

509

true,

510

false,

511

false,

512

)

513

if err != nil {

514

log.Fatal(err)

515

}

516

517

err = registry.DefineParameterType(uuidType)

518

if err != nil {

519

log.Fatal(err)

520

}

521

522

// Verify registration

523

retrieved := registry.LookupByTypeName("uuid")

524

fmt.Printf("UUID type registered: %v\n", retrieved != nil)

525

fmt.Printf("Same instance: %v\n", retrieved == uuidType)

526

527

// Set custom default transformer

528

registry.SetDefaultParameterTransformer(&CustomTransformer{})

529

530

// Test with anonymous parameter and type hint

531

expr, _ := cucumberexpressions.NewCucumberExpression("Value is {}", registry)

532

533

// Test with int type hint

534

args, _ := expr.Match("Value is 42", reflect.TypeOf(0))

535

if args != nil {

536

value := args[0].GetValue()

537

fmt.Printf("Anonymous int: %v (type: %T)\n", value, value)

538

}

539

540

// Test with float type hint

541

args, _ = expr.Match("Value is 3.14", reflect.TypeOf(0.0))

542

if args != nil {

543

value := args[0].GetValue()

544

fmt.Printf("Anonymous float: %v (type: %T)\n", value, value)

545

}

546

}

547

```

548

549

### Expression Generation

550

551

Generate Cucumber expressions from example text with Go error handling patterns.

552

553

```go { .api }

554

// CucumberExpressionGenerator generates expressions from example text

555

type CucumberExpressionGenerator struct {

556

parameterTypeRegistry *ParameterTypeRegistry

557

}

558

559

// NewCucumberExpressionGenerator creates generator with parameter type registry

560

func NewCucumberExpressionGenerator(parameterTypeRegistry *ParameterTypeRegistry) *CucumberExpressionGenerator

561

562

// GenerateExpressions creates expressions from example text

563

func (c *CucumberExpressionGenerator) GenerateExpressions(text string) ([]*GeneratedExpression, error)

564

565

// GeneratedExpression contains generated expression with metadata

566

type GeneratedExpression struct {

567

source string

568

parameterTypes []*ParameterType

569

}

570

571

// Source returns the generated expression string

572

func (g *GeneratedExpression) Source() string

573

574

// ParameterTypes returns parameter types in declaration order

575

func (g *GeneratedExpression) ParameterTypes() []*ParameterType

576

577

// ParameterNames returns parameter names for code generation

578

func (g *GeneratedExpression) ParameterNames() []string

579

```

580

581

**Usage Examples:**

582

583

```go

584

package main

585

586

import (

587

"fmt"

588

"log"

589

590

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

591

)

592

593

func main() {

594

registry := cucumberexpressions.NewParameterTypeRegistry()

595

generator := cucumberexpressions.NewCucumberExpressionGenerator(registry)

596

597

// Generate from text with integers

598

expressions, err := generator.GenerateExpressions("I have 42 cucumbers")

599

if err != nil {

600

log.Fatal(err)

601

}

602

603

if len(expressions) > 0 {

604

best := expressions[0]

605

fmt.Printf("Generated: %s\n", best.Source()) // "I have {int} cucumbers"

606

fmt.Printf("Parameter names: %v\n", best.ParameterNames())

607

608

// Generate Go step definition

609

fmt.Println("Go step definition:")

610

paramTypes := make([]string, len(best.ParameterTypes()))

611

paramNames := best.ParameterNames()

612

for i, pt := range best.ParameterTypes() {

613

paramTypes[i] = goType(pt.Name())

614

}

615

616

fmt.Printf("func iHaveCucumbers(")

617

for i, name := range paramNames {

618

if i > 0 {

619

fmt.Print(", ")

620

}

621

fmt.Printf("%s %s", name, paramTypes[i])

622

}

623

fmt.Println(") error {")

624

fmt.Println(" // Implementation here")

625

fmt.Println(" return nil")

626

fmt.Println("}")

627

}

628

629

// Generate from complex text

630

expressions, err = generator.GenerateExpressions("User alice with age 25 has balance 123.45")

631

if err != nil {

632

log.Fatal(err)

633

}

634

635

fmt.Println("\nGenerated options:")

636

for i, expr := range expressions {

637

if i >= 3 { // Show first 3 options

638

break

639

}

640

641

typeNames := make([]string, len(expr.ParameterTypes()))

642

for j, pt := range expr.ParameterTypes() {

643

typeNames[j] = pt.Name()

644

}

645

646

fmt.Printf("%d. %s (%v)\n", i+1, expr.Source(), typeNames)

647

}

648

649

// Generate from text with strings

650

expressions, err = generator.GenerateExpressions(`I select "Premium Plan" option`)

651

if err != nil {

652

log.Fatal(err)

653

}

654

655

if len(expressions) > 0 {

656

fmt.Printf("String example: %s\n", expressions[0].Source()) // "I select {string} option"

657

}

658

}

659

660

func goType(paramTypeName string) string {

661

switch paramTypeName {

662

case "int":

663

return "int"

664

case "float":

665

return "float64"

666

case "string", "word":

667

return "string"

668

case "bigdecimal":

669

return "float64" // or big.Float for true precision

670

default:

671

return "interface{}"

672

}

673

}

674

```

675

676

### Argument Extraction

677

678

Extract matched arguments with Go-style value access and error handling.

679

680

```go { .api }

681

// Argument represents a matched argument with type information

682

type Argument struct {

683

group *Group

684

parameterType *ParameterType

685

}

686

687

// BuildArguments creates arguments from tree regexp match

688

func BuildArguments(treeRegexp *TreeRegexp, text string, parameterTypes []*ParameterType) []*Argument

689

690

// GetValue returns the transformed value

691

func (a *Argument) GetValue() interface{}

692

693

// GetParameterType returns the parameter type used for transformation

694

func (a *Argument) GetParameterType() *ParameterType

695

696

// Group returns the matched group with position information

697

func (a *Argument) Group() *Group

698

699

// Group represents a matched group with position and hierarchy

700

type Group struct {

701

Value *string

702

Start int

703

End int

704

Children []*Group

705

}

706

707

// GetValue returns the matched text value

708

func (g *Group) GetValue() *string

709

710

// GetStart returns start position in source text

711

func (g *Group) GetStart() int

712

713

// GetEnd returns end position in source text

714

func (g *Group) GetEnd() int

715

716

// GetChildren returns child groups

717

func (g *Group) GetChildren() []*Group

718

```

719

720

**Usage Examples:**

721

722

```go

723

package main

724

725

import (

726

"fmt"

727

"log"

728

729

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

730

)

731

732

func main() {

733

registry := cucumberexpressions.NewParameterTypeRegistry()

734

expr, err := cucumberexpressions.NewCucumberExpression("User {word} has {int} items", registry)

735

if err != nil {

736

log.Fatal(err)

737

}

738

739

args, err := expr.Match("User alice has 42 items")

740

if err != nil {

741

log.Fatal(err)

742

}

743

744

if args != nil {

745

// Type-safe value access

746

username := args[0].GetValue().(string) // "alice"

747

itemCount := args[1].GetValue().(int) // 42

748

749

fmt.Printf("User: %s, Items: %d\n", username, itemCount)

750

751

// Parameter type information

752

fmt.Printf("First param type: %s\n", args[0].GetParameterType().Name()) // "word"

753

fmt.Printf("Second param type: %s\n", args[1].GetParameterType().Name()) // "int"

754

755

// Position information

756

usernameGroup := args[0].Group()

757

if usernameGroup.GetValue() != nil {

758

fmt.Printf("Username '%s' at position %d-%d\n",

759

*usernameGroup.GetValue(),

760

usernameGroup.GetStart(),

761

usernameGroup.GetEnd())

762

}

763

764

itemGroup := args[1].Group()

765

if itemGroup.GetValue() != nil {

766

fmt.Printf("Item count '%s' at position %d-%d\n",

767

*itemGroup.GetValue(),

768

itemGroup.GetStart(),

769

itemGroup.GetEnd())

770

}

771

}

772

}

773

```

774

775

### Built-in Parameter Types

776

777

Go implementation provides built-in parameter types with appropriate Go type conversion.

778

779

```go { .api }

780

// Built-in parameter types in Go implementation:

781

782

{int} // Converts to int

783

{byte} // Converts to int8 (byte)

784

{short} // Converts to int16

785

{long} // Converts to int64

786

{float} // Converts to float32

787

{double} // Converts to float64

788

{biginteger} // Converts to big.Int

789

{bigdecimal} // Converts to big.Float

790

{word} // Returns as string (single word)

791

{string} // Returns as string (removes quotes)

792

{} // Anonymous - uses ParameterByTypeTransformer

793

```

794

795

**Usage Examples:**

796

797

```go

798

package main

799

800

import (

801

"fmt"

802

"log"

803

"math/big"

804

805

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

806

)

807

808

func main() {

809

registry := cucumberexpressions.NewParameterTypeRegistry()

810

811

// Test numeric built-in types

812

expr, err := cucumberexpressions.NewCucumberExpression(

813

"Numbers: {int} {float} {double} {word} {string}",

814

registry,

815

)

816

if err != nil {

817

log.Fatal(err)

818

}

819

820

args, err := expr.Match(`Numbers: 42 3.14 2.718281828 hello "world test"`)

821

if err != nil {

822

log.Fatal(err)

823

}

824

825

if args != nil {

826

intVal := args[0].GetValue().(int)

827

floatVal := args[1].GetValue().(float32)

828

doubleVal := args[2].GetValue().(float64)

829

wordVal := args[3].GetValue().(string)

830

stringVal := args[4].GetValue().(string)

831

832

fmt.Printf("int: %v (%T)\n", intVal, intVal) // 42 (int)

833

fmt.Printf("float: %v (%T)\n", floatVal, floatVal) // 3.14 (float32)

834

fmt.Printf("double: %v (%T)\n", doubleVal, doubleVal) // 2.718281828 (float64)

835

fmt.Printf("word: %v (%T)\n", wordVal, wordVal) // hello (string)

836

fmt.Printf("string: %v (%T)\n", stringVal, stringVal) // world test (string)

837

}

838

839

// Test big number types

840

bigExpr, err := cucumberexpressions.NewCucumberExpression(

841

"Big numbers: {biginteger} {bigdecimal}",

842

registry,

843

)

844

if err != nil {

845

log.Fatal(err)

846

}

847

848

bigArgs, err := bigExpr.Match("Big numbers: 12345678901234567890 123.456789012345")

849

if err != nil {

850

log.Fatal(err)

851

}

852

853

if bigArgs != nil {

854

bigIntVal := bigArgs[0].GetValue().(*big.Int)

855

bigDecVal := bigArgs[1].GetValue().(*big.Float)

856

857

fmt.Printf("biginteger: %v (%T)\n", bigIntVal, bigIntVal) // big.Int

858

fmt.Printf("bigdecimal: %v (%T)\n", bigDecVal, bigDecVal) // big.Float

859

}

860

}

861

```

862

863

### Integration with Go Testing Frameworks

864

865

Common patterns for integrating with Go testing frameworks and BDD tools.

866

867

```go

868

// Testing with standard Go testing package

869

package main

870

871

import (

872

"testing"

873

874

cucumberexpressions "github.com/cucumber/cucumber-expressions/go/v18"

875

)

876

877

func TestCucumberExpressions(t *testing.T) {

878

registry := cucumberexpressions.NewParameterTypeRegistry()

879

880

t.Run("ParameterExtraction", func(t *testing.T) {

881

expr, err := cucumberexpressions.NewCucumberExpression("User {word} has {int} items", registry)

882

if err != nil {

883

t.Fatal(err)

884

}

885

886

args, err := expr.Match("User alice has 42 items")

887

if err != nil {

888

t.Fatal(err)

889

}

890

891

if args == nil {

892

t.Fatal("Expected match but got nil")

893

}

894

895

if len(args) != 2 {

896

t.Fatalf("Expected 2 arguments, got %d", len(args))

897

}

898

899

username := args[0].GetValue().(string)

900

if username != "alice" {

901

t.Errorf("Expected username 'alice', got '%s'", username)

902

}

903

904

itemCount := args[1].GetValue().(int)

905

if itemCount != 42 {

906

t.Errorf("Expected item count 42, got %d", itemCount)

907

}

908

})

909

910

t.Run("CustomParameterType", func(t *testing.T) {

911

// Define custom parameter type for testing

912

colorRegexp, _ := regexp.Compile("red|green|blue")

913

colorType, err := cucumberexpressions.NewParameterType(

914

"color",

915

[]*regexp.Regexp{colorRegexp},

916

"string",

917

func(args ...*string) interface{} {

918

if len(args) > 0 && args[0] != nil {

919

return strings.ToUpper(*args[0])

920

}

921

return nil

922

},

923

true,

924

false,

925

false,

926

)

927

if err != nil {

928

t.Fatal(err)

929

}

930

931

err = registry.DefineParameterType(colorType)

932

if err != nil {

933

t.Fatal(err)

934

}

935

936

expr, err := cucumberexpressions.NewCucumberExpression("I have a {color} car", registry)

937

if err != nil {

938

t.Fatal(err)

939

}

940

941

args, err := expr.Match("I have a red car")

942

if err != nil {

943

t.Fatal(err)

944

}

945

946

if args == nil || len(args) != 1 {

947

t.Fatal("Expected 1 argument")

948

}

949

950

color := args[0].GetValue().(string)

951

if color != "RED" {

952

t.Errorf("Expected color 'RED', got '%s'", color)

953

}

954

})

955

}

956

957

// Step definition helper for BDD frameworks

958

type StepDefinition struct {

959

Pattern string

960

Expression cucumberexpressions.Expression

961

Handler interface{}

962

}

963

964

func NewStepDefinition(pattern string, registry *cucumberexpressions.ParameterTypeRegistry, handler interface{}) (*StepDefinition, error) {

965

expr, err := cucumberexpressions.NewCucumberExpression(pattern, registry)

966

if err != nil {

967

return nil, err

968

}

969

970

return &StepDefinition{

971

Pattern: pattern,

972

Expression: expr,

973

Handler: handler,

974

}, nil

975

}

976

977

func (sd *StepDefinition) Match(text string) ([]*cucumberexpressions.Argument, error) {

978

return sd.Expression.Match(text)

979

}

980

981

// Example usage in BDD framework integration

982

func ExampleBDDIntegration() {

983

registry := cucumberexpressions.NewParameterTypeRegistry()

984

985

// Define step definitions

986

stepDefs := []*StepDefinition{}

987

988

// Given step

989

givenStep, _ := NewStepDefinition(

990

"I have {int} cucumbers",

991

registry,

992

func(count int) error {

993

// Implementation

994

fmt.Printf("Setting cucumber count to %d\n", count)

995

return nil

996

},

997

)

998

stepDefs = append(stepDefs, givenStep)

999

1000

// When step

1001

whenStep, _ := NewStepDefinition(

1002

"I eat {int} cucumber(s)",

1003

registry,

1004

func(count int) error {

1005

// Implementation

1006

fmt.Printf("Eating %d cucumber(s)\n", count)

1007

return nil

1008

},

1009

)

1010

stepDefs = append(stepDefs, whenStep)

1011

1012

// Then step

1013

thenStep, _ := NewStepDefinition(

1014

"I should have {int} cucumber(s) left",

1015

registry,

1016

func(count int) error {

1017

// Implementation

1018

fmt.Printf("Checking %d cucumber(s) remaining\n", count)

1019

return nil

1020

},

1021

)

1022

stepDefs = append(stepDefs, thenStep)

1023

1024

// Execute scenario

1025

scenario := []string{

1026

"I have 5 cucumbers",

1027

"I eat 2 cucumbers",

1028

"I should have 3 cucumbers left",

1029

}

1030

1031

for _, step := range scenario {

1032

for _, stepDef := range stepDefs {

1033

args, err := stepDef.Match(step)

1034

if err != nil {

1035

fmt.Printf("Error matching step: %v\n", err)

1036

continue

1037

}

1038

if args != nil {

1039

fmt.Printf("Matched: %s\n", step)

1040

// Call handler with extracted arguments

1041

break

1042

}

1043

}

1044

}

1045

}

1046

```

1047

1048

The Go implementation provides idiomatic Go patterns with comprehensive error handling, reflection-based type hints, and efficient regex matching while maintaining full compatibility with the Cucumber Expressions specification and enabling seamless integration with Go testing frameworks.