Looks like an issue occurs when there are lots of ConfigureAcronym calls and ToCamel is called concurrently. I'm not exactly sure why this would happen but below is how to replicate the problem in a unit test:
concurrency_test.go
func TestConcurrency(t *testing.T) {
for i := 0; i < 10000; i++ {
go doConvert()
}
}
func doConvert() {
var snakes = []string{"code", "exchange", "pe_ratio", "profit_margin", "updated_date"}
for _, v := range snakes {
_ = convertDatabaseNameToCamelCase(v)
}
}
func convertDatabaseNameToCamelCase(d string) (s string) {
ConfigureAcronym("price_book_mrq", "PriceBookMRQ")
ConfigureAcronym("pe_ratio", "PERatio")
ConfigureAcronym("peg_ratio", "PEGRatio")
ConfigureAcronym("eps_estimate_current_year", "EPSEstimateCurrentYear")
ConfigureAcronym("eps_estimate_next_year", "EPSEstimateNextYear")
ConfigureAcronym("eps_estimate_next_quarter", "EPSNextQuarter")
ConfigureAcronym("eps_estimate_current_quarter", "EPSEstimateCurrentQuarter")
ConfigureAcronym("ebitda", "EBITDA")
ConfigureAcronym("operating_margin_ttm", "OperatingMarginTTM")
ConfigureAcronym("return_on_assets_ttm", "ReturnOnAssetsTTM")
ConfigureAcronym("return_on_equity_ttm", "ReturnOnEquityTTM")
ConfigureAcronym("revenue_ttm", "RevenueTTM")
ConfigureAcronym("revenue_per_share_ttm", "RevenuePerShareTTM")
ConfigureAcronym("quarterly_revenue_growth_yoy", "QuarterlyRevenueGrowthYOY")
ConfigureAcronym("gross_profit_ttm", "GrossProfitTTM")
ConfigureAcronym("diluted_eps_ttm", "DilutedEpsTTM")
ConfigureAcronym("quarterly_earnings_growth_yoy", "QuarterlyEarningsGrowthYOY")
ConfigureAcronym("two_hundred_day_ma", "TwoHundredDayMA")
ConfigureAcronym("trailing_pe", "TrailingPE")
ConfigureAcronym("forward_pe", "ForwardPE")
ConfigureAcronym("price_sales_ttm", "PriceSalesTTM")
ConfigureAcronym("price_book_mrq", "PriceBookMRQ")
s = ToCamel(d)
return
}
If you run this test and send the output to a file the panic is reproducible. If you do not output to a file then the standard output to the console actually slows down the process enough that the issue occurs much less frequently.
var uppercaseAcronym = map[string]string{
"ID": "id",
}
// ConfigureAcronym allows you to add additional words which will be considered acronyms
func ConfigureAcronym(key, val string) {
uppercaseAcronym[key] = val
}
To:
var uppercaseAcronym = sync.Map{}
// ConfigureAcronym allows you to add additional words which will be considered acronyms
func ConfigureAcronym(key, val string) {
uppercaseAcronym.Store(key, val)
}
Change camel.go toCamelInitCase lines 39-41 from:
if a, ok := uppercaseAcronym[s]; ok {
s = a
}
To:
if a, ok := uppercaseAcronym.Load(s); ok {
s, _ = a.(string)
}
The you need to add the following to camel_test.go
ConfigureAcronym("ID", "Id")
I have a version of this fix as a branch if you want it.
Looks like an issue occurs when there are lots of ConfigureAcronym calls and ToCamel is called concurrently. I'm not exactly sure why this would happen but below is how to replicate the problem in a unit test:
concurrency_test.go
If you run this test and send the output to a file the panic is reproducible. If you do not output to a file then the standard output to the console actually slows down the process enough that the issue occurs much less frequently.
go test -run TestConcurrency > deleteme.txt
Will produce:
The fix:
Change acronyms.go from:
To:
Change camel.go toCamelInitCase lines 39-41 from:
To:
The you need to add the following to camel_test.go
ConfigureAcronym("ID", "Id")
I have a version of this fix as a branch if you want it.