Files
lo/docs/data/core-substring.md
T
d-enk 68f827d9bf perf: optimize Substring to work directly with strings instead of converting to runes (#822)
* perf: optimize Substring to work directly with strings instead of converting to runes

- Rewrite Substring to iterate over string bytes directly, avoiding full []rune conversion
- Improve performance for long strings by only processing necessary portions
- Add comprehensive test cases for Unicode handling, invalid UTF-8, and edge cases
- Add BenchmarkSubstring to measure performance improvements
- Improve documentation with detailed parameter descriptions
- Handle invalid UTF-8 sequences by converting to []rune when needed

Bencstat:

                   │    old.txt    │               new.txt               │
                   │    sec/op     │    sec/op     vs base               │
Substring/{10_10}-4    558.85n ±  9%   39.75n ± 10%  -92.89% (p=0.000 n=8)
Substring/{50_50}-4    783.10n ±  6%   85.15n ±  5%  -89.13% (p=0.000 n=8)
Substring/{50_45}-4    773.30n ±  3%   126.5n ±  7%  -83.65% (p=0.000 n=8)
Substring/{-50_50}-4   794.00n ±  2%   177.6n ±  7%  -77.63% (p=0.000 n=8)
Substring/{-10_10}-4   542.85n ± 20%   41.82n ±  6%  -92.30% (p=0.000 n=8)
geomean               680.4n         79.52n        -88.31%

                   │  old.txt   │               new.txt                │
                   │    B/op    │   B/op    vs base                    │
Substring/{10_10}-4    432.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
Substring/{50_50}-4    480.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
Substring/{50_45}-4    464.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
Substring/{-50_50}-4   480.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
Substring/{-10_10}-4   432.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                   │  old.txt   │                new.txt                 │
                   │ allocs/op  │ allocs/op   vs base                    │
Substring/{10_10}-4    2.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
Substring/{50_50}-4    2.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
Substring/{50_45}-4    2.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
Substring/{-50_50}-4   2.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
Substring/{-10_10}-4   2.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)

* Enhance substring documentation with Unicode details

Returns a substring starting at the given offset with the specified length. Supports negative offsets; out-of-bounds are clamped. Operates on Unicode runes (characters) and is optimized for zero allocations.

---------

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-02-27 22:19:20 +01:00

55 lines
1.4 KiB
Markdown

---
name: Substring
slug: substring
sourceRef: string.go#L105
category: core
subCategory: string
playUrl: https://go.dev/play/p/TQlxQi82Lu1
variantHelpers:
- core#string#substring
similarHelpers:
- core#string#chunkstring
- core#string#runelength
- core#string#ellipsis
- core#string#words
- core#slice#replace
- core#slice#replaceall
position: 10
signatures:
- "func Substring[T ~string](str T, offset int, length uint) T"
---
Returns a substring starting at the given offset with the specified length. Supports negative offsets; out-of-bounds are clamped. Operates on Unicode runes (characters) and is optimized for zero allocations.
```go
// Basic usage
result := lo.Substring("hello", 2, 3)
// result: "llo"
// Negative offset - counts from end
result = lo.Substring("hello", -4, 3)
// result: "ell"
// Length longer than string - clamped to available characters
result = lo.Substring("hello", 1, 10)
// result: "ello" (only 4 characters available from position 1)
// Zero length - returns empty string
result = lo.Substring("hello", 1, 0)
// result: ""
// Offset beyond string length - returns empty string
result = lo.Substring("hello", 10, 3)
// result: ""
// With Unicode strings (rune-aware)
result = lo.Substring("héllo", 1, 3)
// result: "él"
// Negative offset with negative values clamped
result = lo.Substring("hello", -10, 3)
// result: "hel" (offset clamped to 0)
```