Skip to content

Conversation

songzhibin97
Copy link

When some of the built-in conditions are not enough, let the user pass in a handler function to supplement the

@CLAassistant
Copy link

CLAassistant commented Jan 10, 2025

CLA assistant check
All committers have signed the CLA.

@sagikazarmark
Copy link
Collaborator

Thanks for the contribution, but I'm not entirely sure this solves a wide enough use case to include it in the library.

@songzhibin97
Copy link
Author

Thanks for the contribution, but I'm not entirely sure this solves a wide enough use case to include it in the library.

Thank you for the feedback. I'd like to clarify the motivation behind this contribution.

The "plus functions" are designed to address gaps in the existing case coverage of the cast library, rather than adding entirely new functionality. Currently, when cast encounters an input type it doesn't handle, it returns zero values, which can be problematic in production scenarios.

The problem this solves:

  • Cast library has excellent coverage for common types, but inevitably misses edge cases
  • When cast fails, applications often need to implement their own fallback logic anyway
  • This creates inconsistent casting behavior across codebases

The solution:

  • The P functions provide a clean way to extend the existing case enumeration
  • They only invoke the fallback function when cast's built-in logic fails
  • This maintains cast's performance for supported cases while gracefully handling unsupported ones

Real-world example:

// Instead of this pattern:
result := cast.ToString(value)
if result == "" && value != nil {
    result = myCustomStringConverter(value)
}

// You can do:
result := cast.ToStringP(myCustomStringConverter, value)

This essentially allows users to complete the case coverage that cast started, rather than replacing it. It's about making cast more robust for edge cases, not changing its core purpose.

Would you be open to reconsidering this as a way to make cast more complete rather than adding scope creep?

- Accept upstream's new structure with generics
- Remove caste.go as it was deleted upstream
- Code is now organized into separate files with code generation
- Add generic ToP[T] and ToPE[T] functions for Basic types
- Add specific plus functions for all cast types (ToBoolP, ToStringP, etc.)
- Add plus functions for maps and slices with fallback support
- Maintain compatibility with upstream's new generic architecture
- Add comprehensive unit tests covering all plus functions
- Add real-world usage examples demonstrating practical scenarios
- Plus functions provide fallback logic when standard casting fails
- Enables extending cast's case coverage without modifying core library

This addresses gaps in cast's type coverage by allowing users to provide
custom fallback functions when the built-in conversion logic fails.
- Document all plus function variants and usage patterns
- Provide practical examples for common use cases
- Explain benefits and performance characteristics
- Include guidance on when to use plus functions
@sagikazarmark
Copy link
Collaborator

@songzhibin97 thanks for the thorough explanation. It's clear you've thought this through very well and you provided a great PR.

Let me sleep on it. I understand the use case, but adding new functions feels a bit weird.


Here is a quick idea, but I haven't fully thought it through:

How about something like cast.ToValue(&target, value), where the target implements the custom logic?

- Remove all plus functions (ToPE, ToP, etc.) as suggested by project author
- Add ValueSetter interface for custom conversion logic
- Add ToValue function that delegates to target types
- Update examples to use new ToValue API
- Maintain backward compatibility with existing functions
- Add .idea/ to .gitignore
- Better reflects the new ToValue API functionality
- Removes confusion about plus functions
- Remove toPFunc and toPFuncWithParams from generator
- Remove all PE functions from map.go and time.go
- Regenerate zz_generated.go without plus functions
- All tests pass, only ToValue API remains as replacement
- Add support for all slice types ([]string, []int, []bool, etc.)
- Add support for all map types (map[string]string, map[string]any, etc.)
- Add comprehensive examples for slices and maps
- ToValue now covers 100% of original plus functions functionality
- All tests pass, complete replacement for plus functions

实现 ValueSetter 接口支持自定义类型转换

- 添加 ValueSetter 接口定义,允许自定义类型实现 SetValue 方法
- 在所有转换函数的 default 分支中集成 ValueSetter 接口检查
- 修改的函数包括:ToBoolE, ToStringE, toNumberE, ToTimeInDefaultLocationE, ToDurationE, ToSliceE
- 保持向后兼容性,标准转换逻辑优先执行
- 添加完整的单元测试和示例代码
- 所有测试通过,功能验证完成

这个实现响应了项目维护者关于嵌入自定义转换逻辑的建议,
避免了添加新函数,而是将扩展能力直接集成到现有转换函数中。
- 使用 go fmt 修复 map.go 和 slice.go 的格式问题
- 移除多余的空行
- 确保代码符合 Go 格式规范
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants